kodu 2.1.3 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/core/registry/registry.service.test.ts +82 -0
- package/__tests__/shared/runbook/runbook.service.test.ts +104 -0
- package/dist/package.json +1 -1
- package/dist/src/app.module.js +6 -0
- package/dist/src/app.module.js.map +1 -1
- package/dist/src/commands/ops/ops-add.command.d.ts +18 -0
- package/dist/src/commands/ops/ops-add.command.js +102 -0
- package/dist/src/commands/ops/ops-add.command.js.map +1 -0
- package/dist/src/commands/ops/ops-init.command.d.ts +22 -0
- package/dist/src/commands/ops/ops-init.command.js +130 -0
- package/dist/src/commands/ops/ops-init.command.js.map +1 -0
- package/dist/src/commands/ops/ops-list.command.d.ts +12 -0
- package/dist/src/commands/ops/ops-list.command.js +73 -0
- package/dist/src/commands/ops/ops-list.command.js.map +1 -0
- package/dist/src/commands/ops/ops-path.command.d.ts +9 -0
- package/dist/src/commands/ops/ops-path.command.js +52 -0
- package/dist/src/commands/ops/ops-path.command.js.map +1 -0
- package/dist/src/commands/ops/ops-runbook.command.d.ts +12 -0
- package/dist/src/commands/ops/ops-runbook.command.js +81 -0
- package/dist/src/commands/ops/ops-runbook.command.js.map +1 -0
- package/dist/src/commands/ops/ops-status.command.d.ts +11 -0
- package/dist/src/commands/ops/ops-status.command.js +62 -0
- package/dist/src/commands/ops/ops-status.command.js.map +1 -0
- package/dist/src/commands/ops/ops-use.command.d.ts +12 -0
- package/dist/src/commands/ops/ops-use.command.js +76 -0
- package/dist/src/commands/ops/ops-use.command.js.map +1 -0
- package/dist/src/commands/ops/ops.command.d.ts +7 -0
- package/dist/src/commands/ops/ops.command.js +56 -0
- package/dist/src/commands/ops/ops.command.js.map +1 -0
- package/dist/src/commands/ops/ops.helpers.d.ts +2 -0
- package/dist/src/commands/ops/ops.helpers.js +11 -0
- package/dist/src/commands/ops/ops.helpers.js.map +1 -0
- package/dist/src/commands/ops/ops.module.d.ts +2 -0
- package/dist/src/commands/ops/ops.module.js +36 -0
- package/dist/src/commands/ops/ops.module.js.map +1 -0
- package/dist/src/core/registry/registry.module.d.ts +2 -0
- package/dist/src/core/registry/registry.module.js +22 -0
- package/dist/src/core/registry/registry.module.js.map +1 -0
- package/dist/src/core/registry/registry.schema.d.ts +24 -0
- package/dist/src/core/registry/registry.schema.js +21 -0
- package/dist/src/core/registry/registry.schema.js.map +1 -0
- package/dist/src/core/registry/registry.service.d.ts +16 -0
- package/dist/src/core/registry/registry.service.js +91 -0
- package/dist/src/core/registry/registry.service.js.map +1 -0
- package/dist/src/shared/runbook/runbook.module.d.ts +2 -0
- package/dist/src/shared/runbook/runbook.module.js +22 -0
- package/dist/src/shared/runbook/runbook.module.js.map +1 -0
- package/dist/src/shared/runbook/runbook.service.d.ts +20 -0
- package/dist/src/shared/runbook/runbook.service.js +118 -0
- package/dist/src/shared/runbook/runbook.service.js.map +1 -0
- package/dist/src/shared/runbook/runbook.templates.d.ts +6 -0
- package/dist/src/shared/runbook/runbook.templates.js +49 -0
- package/dist/src/shared/runbook/runbook.templates.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/registry.schema.json +39 -0
- package/scripts/generate-json-schema.ts +14 -5
- package/skills/ac/SKILL.md +239 -0
- package/skills/al/SKILL.md +98 -0
- package/skills/audit/SKILL.md +205 -0
- package/skills/audit/audit-baseline-template.yml +188 -0
- package/skills/audit/runtime-detect.md +64 -0
- package/skills/audit/stacks/_generic.md +41 -0
- package/skills/audit/stacks/_registry.md +47 -0
- package/skills/audit/stacks/go.md +66 -0
- package/skills/audit/stacks/java.md +44 -0
- package/skills/audit/stacks/node.md +57 -0
- package/skills/audit/stacks/python.md +45 -0
- package/skills/audit/stacks/rust.md +44 -0
- package/skills/audit-api-contracts/SKILL.md +201 -0
- package/skills/audit-architecture/SKILL.md +200 -0
- package/skills/audit-bugs/SKILL.md +226 -0
- package/skills/audit-concurrency/SKILL.md +197 -0
- package/skills/audit-deployment/SKILL.md +218 -0
- package/skills/audit-docs/SKILL.md +209 -0
- package/skills/audit-errors/SKILL.md +216 -0
- package/skills/audit-logging/SKILL.md +197 -0
- package/skills/audit-matrix/SKILL.md +245 -0
- package/skills/audit-meta/SKILL.md +120 -0
- package/skills/audit-naming/SKILL.md +200 -0
- package/skills/audit-owasp/SKILL.md +223 -0
- package/skills/audit-performance/SKILL.md +199 -0
- package/skills/audit-reinvention/SKILL.md +214 -0
- package/skills/audit-secrets/SKILL.md +198 -0
- package/skills/audit-tests/SKILL.md +210 -0
- package/skills/audit-validation/SKILL.md +206 -0
- package/skills/audit-verify/SKILL.md +139 -0
- package/skills/audit-yagni/SKILL.md +188 -0
- package/skills/generate-project-docs/SKILL.md +380 -0
- package/skills/ops/SKILL.md +94 -0
- package/skills/post-call-task-builder/SKILL.md +419 -0
- package/skills/skills-best-practices/SKILL.md +415 -0
- package/src/app.module.ts +6 -0
- package/src/commands/ops/ops-add.command.ts +83 -0
- package/src/commands/ops/ops-init.command.ts +125 -0
- package/src/commands/ops/ops-list.command.ts +57 -0
- package/src/commands/ops/ops-path.command.ts +38 -0
- package/src/commands/ops/ops-runbook.command.ts +74 -0
- package/src/commands/ops/ops-status.command.ts +47 -0
- package/src/commands/ops/ops-use.command.ts +76 -0
- package/src/commands/ops/ops.command.ts +42 -0
- package/src/commands/ops/ops.helpers.ts +20 -0
- package/src/commands/ops/ops.module.ts +23 -0
- package/src/core/registry/registry.module.ts +9 -0
- package/src/core/registry/registry.schema.ts +46 -0
- package/src/core/registry/registry.service.ts +128 -0
- package/src/shared/runbook/runbook.module.ts +9 -0
- package/src/shared/runbook/runbook.service.ts +164 -0
- package/src/shared/runbook/runbook.templates.ts +66 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: audit-concurrency
|
|
3
|
+
description: >
|
|
4
|
+
Аудит управления состоянием и конкурентности: race conditions, deadlocks, shared mutable state,
|
|
5
|
+
неатомарные операции. Запускай при /audit-concurrency.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Правило применимости (Relevance Rule)
|
|
9
|
+
|
|
10
|
+
Применим к коду с параллельными операциями, shared state, кэшированием, транзакциями БД, очередями, WebSocket. Для однопоточных скриптов без параллелизма — верни пустой ответ.
|
|
11
|
+
|
|
12
|
+
## Runtime Detection & Stack Profile
|
|
13
|
+
|
|
14
|
+
Этот аудит стек-агностичен: проверки сформулированы нейтрально, а конкретика
|
|
15
|
+
(инструменты, идиомы, анти-паттерны, примеры) берётся из профиля стека.
|
|
16
|
+
|
|
17
|
+
1. **Профиль передан контекстом?** Если оркестратор `/audit` передал
|
|
18
|
+
`runtime=<id>` и/или содержимое профиля — используй его, шаги 2–3 пропусти.
|
|
19
|
+
|
|
20
|
+
2. **Иначе определи РОВНО ОДИН рантайм** этого каталога:
|
|
21
|
+
```bash
|
|
22
|
+
if [ -f package.json ]; then echo "runtime=node"
|
|
23
|
+
elif [ -f go.mod ]; then echo "runtime=go"
|
|
24
|
+
elif [ -f pyproject.toml ] || [ -f requirements.txt ] || [ -f setup.py ]; then echo "runtime=python"
|
|
25
|
+
elif [ -f Cargo.toml ]; then echo "runtime=rust"
|
|
26
|
+
elif [ -f pom.xml ] || ls build.gradle* settings.gradle* >/dev/null 2>&1; then echo "runtime=java"
|
|
27
|
+
else echo "runtime=generic"; fi
|
|
28
|
+
```
|
|
29
|
+
Один запуск = один рантайм; не миксуй backend и frontend. Если найдено
|
|
30
|
+
несколько маркеров (монорепо) — выбери соответствующий текущему scope/анализируемым
|
|
31
|
+
файлам и зафиксируй выбор в разделе Audit Coverage.
|
|
32
|
+
|
|
33
|
+
3. **Загрузи профиль** через Read: `./skills/audit/stacks/<runtime>.md`
|
|
34
|
+
(fallback `./skills/audit/stacks/_generic.md`, если файл не найден).
|
|
35
|
+
|
|
36
|
+
Дальше используй профиль:
|
|
37
|
+
- **Инструменты** — из секции «Tooling by category» профиля (раздел
|
|
38
|
+
«Инструментальная поддержка» ниже ссылается на категории, а не на команды).
|
|
39
|
+
- **Ожидания PASS** — из «Idioms»; **формулировки FAIL** — из «Anti-patterns».
|
|
40
|
+
- **Точечные подсказки** — из «Check-ID hints» по префиксу `CON-`.
|
|
41
|
+
- Если профиль `tier: general` или `runtime=generic` → стек-специфичные находки
|
|
42
|
+
без однозначного evidence помечай `🔍 UNVERIFIED`, а не `❌ FAIL`. Проверки,
|
|
43
|
+
чей механизм в рантайме отсутствует, помечай `N/A`.
|
|
44
|
+
|
|
45
|
+
## Severity Guide
|
|
46
|
+
|
|
47
|
+
| Severity | Критерий назначения |
|
|
48
|
+
|----------|---------------------|
|
|
49
|
+
| 🔴 Critical | RCE, auth bypass, data corruption, необратимый финансовый риск |
|
|
50
|
+
| 🟠 High | Падение production, privilege escalation, утечка данных |
|
|
51
|
+
| 🟡 Medium | Деградация производительности или поддерживаемости без immediate outage |
|
|
52
|
+
| 🟢 Low | Стиль, читаемость, слабое нарушение конвенции |
|
|
53
|
+
|
|
54
|
+
Правило: severity = impact × exploitability × blast radius. Одинаковый паттерн → одинаковый severity между аудитами.
|
|
55
|
+
|
|
56
|
+
## Чеклист
|
|
57
|
+
|
|
58
|
+
| Check ID | Проверка |
|
|
59
|
+
|----------|----------|
|
|
60
|
+
| CON-01 | Параллельные операции запускаются и синхронизируются корректно; результаты дожидаются, фоновые задачи не утекают |
|
|
61
|
+
| CON-02 | Read-modify-write операции выполняются в транзакциях [⚡ dynamic] |
|
|
62
|
+
| CON-03 | Разделяемое изменяемое состояние защищено синхронизацией (синглтоны, кэши, переменные уровня модуля) |
|
|
63
|
+
| CON-04 | Module-level кэш имеет механизм инвалидации |
|
|
64
|
+
| CON-05 | Обработчики событий и webhook-handlers идемпотентны [⚡ dynamic] |
|
|
65
|
+
| CON-06 | Фоновые операции имеют механизм отмены и не блокируют graceful shutdown |
|
|
66
|
+
|
|
67
|
+
## Правила верификации
|
|
68
|
+
|
|
69
|
+
1. **Только чеклист**: оценивай ТОЛЬКО проверки выше. Не добавляй новые.
|
|
70
|
+
2. **Явная верификация = PASS**: ставь `✅ PASS` только если явно проверил механизм (нашёл схему, конфиг, guard) и подтвердил отсутствие нарушения — укажи что именно проверено.
|
|
71
|
+
3. **Нет доказательства = UNVERIFIED**: не можешь указать `файл:строка` ни для нарушения, ни для подтверждения — ставь `🔍 UNVERIFIED`.
|
|
72
|
+
- Проверки с `[⚡ dynamic]` нельзя статически подтвердить — только `🔍 UNVERIFIED` или `❌ FAIL` (при явном evidence), но не `✅ PASS`
|
|
73
|
+
4. **Baseline приоритетен**: check_id есть в `docs/audit-baseline.yml` → `⏸ ACCEPTED`.
|
|
74
|
+
5. **Только 🔴/🟠 FAIL требуют решения**: 🟡/🟢 — решение необязательно.
|
|
75
|
+
|
|
76
|
+
## Evidence Quality Rules
|
|
77
|
+
|
|
78
|
+
Любой `❌ FAIL` обязан содержать:
|
|
79
|
+
- Точный `file:line`
|
|
80
|
+
- Минимальный код-фрагмент (1–3 строки)
|
|
81
|
+
- Causal chain: почему именно это нарушение → какой риск возникает
|
|
82
|
+
|
|
83
|
+
Запрещено:
|
|
84
|
+
- Предполагать runtime behavior без evidence в коде
|
|
85
|
+
- Предполагать prod-конфигурацию по dev-конфигу
|
|
86
|
+
- Предполагать отсутствие middleware без проверки всей router chain
|
|
87
|
+
- Если вывод основан на предположении — только `🔍 UNVERIFIED`
|
|
88
|
+
|
|
89
|
+
## Language Rule
|
|
90
|
+
|
|
91
|
+
Результаты аудита должны быть написаны простым и понятным языком. Избегай сложных терминов, жаргона и абстрактных понятий без необходимости. Общепринятые технические термины (Docker, HTTP, API, JSON, URL) допустимы. Описывай проблемы так, чтобы они были понятны разработчику любого уровня, а не только узкому специалисту в данной области.
|
|
92
|
+
|
|
93
|
+
## Baseline
|
|
94
|
+
|
|
95
|
+
До анализа:
|
|
96
|
+
```bash
|
|
97
|
+
if [ ! -f ./docs/audit-baseline.yml ]; then
|
|
98
|
+
mkdir -p ./docs
|
|
99
|
+
cp ./skills/audit/audit-baseline-template.yml ./docs/audit-baseline.yml 2>/dev/null || \
|
|
100
|
+
printf "accepted: []\n" > ./docs/audit-baseline.yml
|
|
101
|
+
fi
|
|
102
|
+
cat ./docs/audit-baseline.yml
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Контекст анализа
|
|
106
|
+
|
|
107
|
+
> Примеры ниже — иллюстративные (Node/TS). Конкретику текущего рантайма бери из
|
|
108
|
+
> загруженного профиля (`stacks/<runtime>.md`, секции Idioms/Anti-patterns/Check-ID hints).
|
|
109
|
+
|
|
110
|
+
**CON-01 — Параллельные операции запускаются и синхронизируются корректно:**
|
|
111
|
+
- Параллельная операция запущена, но её результат не дожидается (теряется)
|
|
112
|
+
- Фоновая задача утекает — нет пути её завершения
|
|
113
|
+
- Shared state между параллельными операциями без синхронизации
|
|
114
|
+
- В Node: `await` внутри `forEach` (итерация не ждёт промисов); `async` в `Array.map` без `Promise.all` (промисы не ожидаются)
|
|
115
|
+
- В Go: goroutine без `WaitGroup`/`errgroup`/`ctx` → потеря результата или goroutine leak; захват loop-переменной в `for { go f(loopVar) }` (до Go 1.22); незакрытый канал блокирует получателей
|
|
116
|
+
|
|
117
|
+
**CON-02 — Read-modify-write в транзакциях:**
|
|
118
|
+
- SELECT + UPDATE без транзакции (TOCTOU — time-of-check to time-of-use)
|
|
119
|
+
- Двойное списание/начисление без транзакции с блокировкой
|
|
120
|
+
- Check-then-act без атомарности (читаем → проверяем → пишем без lock)
|
|
121
|
+
- Optimistic locking без retry при конфликте версий
|
|
122
|
+
- Кэш-инвалидация между чтением и записью
|
|
123
|
+
|
|
124
|
+
**CON-03 — Разделяемое изменяемое состояние защищено синхронизацией:**
|
|
125
|
+
- Глобальные переменные, изменяемые из нескольких мест без синхронизации
|
|
126
|
+
- Синглтоны с mutable state без синхронизации
|
|
127
|
+
- Closure над изменяемой переменной в async callback
|
|
128
|
+
- Конкурентная запись в один файл/ресурс без координации
|
|
129
|
+
- В Go: map/переменная уровня пакета без `sync.Mutex`/atomic при конкурентном доступе → data race; ловится `go test -race`
|
|
130
|
+
|
|
131
|
+
**CON-04 — Module-level кэш инвалидируется:**
|
|
132
|
+
- Module-level кэш без механизма инвалидации при обновлении данных
|
|
133
|
+
- Кэш без TTL (stale data не обновляется никогда)
|
|
134
|
+
- Нет стратегии обновления кэша при изменении исходных данных
|
|
135
|
+
|
|
136
|
+
**CON-05 — Идемпотентность обработчиков:**
|
|
137
|
+
- Обработчики событий/сообщений без идемпотентности (повторная доставка не безопасна)
|
|
138
|
+
- Нет защиты от дублирующихся webhook-вызовов (нет проверки event_id)
|
|
139
|
+
- Финансовые или критические операции без идемпотентного ключа
|
|
140
|
+
|
|
141
|
+
**CON-06 — Фоновые операции с механизмом отмены:**
|
|
142
|
+
- Фоновая операция запущена без механизма отмены — при shutdown процесс не завершается чисто
|
|
143
|
+
- Background job без timeout и без механизма принудительной остановки
|
|
144
|
+
- Graceful shutdown не ожидает завершения фоновых задач
|
|
145
|
+
- В Node: Promise-цепочка в фоне без `AbortController`/`signal`; `setInterval`/`setImmediate` в request handler без очистки; `Promise.all` с неотменяемыми задачами
|
|
146
|
+
- В Go: фоновая goroutine не слушает `ctx.Done()` → не завершается при shutdown; нужен `context.Context` с проверкой отмены
|
|
147
|
+
|
|
148
|
+
## Граница с другими аудитами
|
|
149
|
+
|
|
150
|
+
- **Идемпотентность** — этот скилл первичный (CON-05). `audit-errors` ссылается сюда.
|
|
151
|
+
- **async/await в forEach** — первичный: `audit-bugs` (BUG-02). `audit-concurrency` (CON-01) фокусируется на параллелизме, а не на синтаксической ошибке.
|
|
152
|
+
|
|
153
|
+
## Формат вывода
|
|
154
|
+
|
|
155
|
+
| Check ID | Проверка | Статус | Уверенность | Доказательство | Решение | Исправлено |
|
|
156
|
+
|----------|----------|--------|-------------|----------------|---------|------------|
|
|
157
|
+
| CON-01 | Параллельные операции запускаются и синхронизируются корректно; результаты дожидаются, фоновые задачи не утекают | ✅ PASS | High | `src/` — async forEach не найден | — | — |
|
|
158
|
+
| CON-02 | Read-modify-write операции выполняются в транзакциях | ❌ FAIL 🔴 | High | `services/wallet.ts:67` | **1. Обернуть в db.transaction() с SELECT FOR UPDATE** \\ 2. Использовать optimistic locking с retry \\ 3. Добавить уникальное ограничение на уровне БД [⚡ dynamic] | Нет |
|
|
159
|
+
| CON-05 | Обработчики событий и webhook-handlers идемпотентны | ⏸ ACCEPTED | Medium | `handlers/stripe.ts:12` | В baseline: идемпотентность обеспечена через event_id [⚡ dynamic] | — |
|
|
160
|
+
|
|
161
|
+
Статусы: `✅ PASS` / `❌ FAIL 🔴` / `❌ FAIL 🟠` / `❌ FAIL 🟡` / `❌ FAIL 🟢` / `⏸ ACCEPTED` / `🔍 UNVERIFIED`
|
|
162
|
+
|
|
163
|
+
Уверенность: `High` — проверил несколько ключевых файлов, паттерн очевиден / `Medium` — проверил выборочно, паттерн вероятен / `Low` — ограниченный контекст, полная уверенность невозможна
|
|
164
|
+
|
|
165
|
+
Для `❌ FAIL`: ровно 3 варианта решения, разделитель `\\`, вариант 1 жирным.
|
|
166
|
+
|
|
167
|
+
`Исправлено`: FAIL → `Нет` (разработчик меняет на `✅ Да` вручную после фикса). PASS / ACCEPTED / UNVERIFIED → `—`.
|
|
168
|
+
|
|
169
|
+
Требования к решениям:
|
|
170
|
+
- Взаимно исключающие (не перефразировки одного и того же)
|
|
171
|
+
- Соответствуют текущему стеку проекта (не предлагать смену фреймворка)
|
|
172
|
+
- Не требуют переписать всю систему — realistic migration cost
|
|
173
|
+
- Вариант 3 может быть «оставить, задокументировать причину» при наличии обоснования
|
|
174
|
+
|
|
175
|
+
В конце отчёта добавь раздел покрытия:
|
|
176
|
+
```
|
|
177
|
+
## Audit Coverage
|
|
178
|
+
Проверено: src/module1/**, src/module2/**
|
|
179
|
+
Пропущено: scripts/**, migrations/**, tests/**
|
|
180
|
+
Файлов проверено: N | Пропущено: N
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Если все PASS — выведи: `✅ Проблем с конкурентностью не обнаружено.`
|
|
184
|
+
|
|
185
|
+
## Сохранение результатов
|
|
186
|
+
|
|
187
|
+
1. Найди папку сессии:
|
|
188
|
+
```bash
|
|
189
|
+
ls -dt ./docs/audits/[0-9]*/ 2>/dev/null | head -1 | sed 's|/$||'
|
|
190
|
+
```
|
|
191
|
+
Если пусто — создай: `mkdir -p ./docs/audits/$(date +"%Y-%m-%d_%H-%M")`
|
|
192
|
+
2. Сохрани через Write: `<AUDIT_DIR>/audit-concurrency.md`
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
# Audit Report: State & Concurrency — <YYYY-MM-DD HH:MM>
|
|
196
|
+
<таблица>
|
|
197
|
+
```
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: audit-deployment
|
|
3
|
+
description: >
|
|
4
|
+
Аудит сборки и деплоя: оптимизация Dockerfile, переменные окружения, CI/CD конфигурации,
|
|
5
|
+
secrets в конфигах, non-root пользователи. Запускай при /audit-deployment.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Правило применимости (Relevance Rule)
|
|
9
|
+
|
|
10
|
+
Применим при наличии Dockerfile, docker-compose.yml, CI/CD конфигов (`.github/workflows`, `gitlab-ci.yml`, `Jenkinsfile`), `.env` файлов, Kubernetes манифестов. Для проектов без deployment конфигурации — верни пустой ответ.
|
|
11
|
+
|
|
12
|
+
## Runtime Detection & Stack Profile
|
|
13
|
+
|
|
14
|
+
Этот аудит стек-агностичен: проверки сформулированы нейтрально, а конкретика
|
|
15
|
+
(инструменты, идиомы, анти-паттерны, примеры) берётся из профиля стека.
|
|
16
|
+
|
|
17
|
+
1. **Профиль передан контекстом?** Если оркестратор `/audit` передал
|
|
18
|
+
`runtime=<id>` и/или содержимое профиля — используй его, шаги 2–3 пропусти.
|
|
19
|
+
|
|
20
|
+
2. **Иначе определи РОВНО ОДИН рантайм** этого каталога:
|
|
21
|
+
```bash
|
|
22
|
+
if [ -f package.json ]; then echo "runtime=node"
|
|
23
|
+
elif [ -f go.mod ]; then echo "runtime=go"
|
|
24
|
+
elif [ -f pyproject.toml ] || [ -f requirements.txt ] || [ -f setup.py ]; then echo "runtime=python"
|
|
25
|
+
elif [ -f Cargo.toml ]; then echo "runtime=rust"
|
|
26
|
+
elif [ -f pom.xml ] || ls build.gradle* settings.gradle* >/dev/null 2>&1; then echo "runtime=java"
|
|
27
|
+
else echo "runtime=generic"; fi
|
|
28
|
+
```
|
|
29
|
+
Один запуск = один рантайм; не миксуй backend и frontend. Если найдено
|
|
30
|
+
несколько маркеров (монорепо) — выбери соответствующий текущему scope/анализируемым
|
|
31
|
+
файлам и зафиксируй выбор в разделе Audit Coverage.
|
|
32
|
+
|
|
33
|
+
3. **Загрузи профиль** через Read: `./skills/audit/stacks/<runtime>.md`
|
|
34
|
+
(fallback `./skills/audit/stacks/_generic.md`, если файл не найден).
|
|
35
|
+
|
|
36
|
+
Дальше используй профиль:
|
|
37
|
+
- **Инструменты** — из секции «Tooling by category» профиля (раздел
|
|
38
|
+
«Инструментальная поддержка» ниже ссылается на категории, а не на команды).
|
|
39
|
+
- **Ожидания PASS** — из «Idioms»; **формулировки FAIL** — из «Anti-patterns».
|
|
40
|
+
- **Точечные подсказки** — из «Check-ID hints» по префиксу `DEP-`.
|
|
41
|
+
- Если профиль `tier: general` или `runtime=generic` → стек-специфичные находки
|
|
42
|
+
без однозначного evidence помечай `🔍 UNVERIFIED`, а не `❌ FAIL`. Проверки,
|
|
43
|
+
чей механизм в рантайме отсутствует, помечай `N/A`.
|
|
44
|
+
|
|
45
|
+
## Severity Guide
|
|
46
|
+
|
|
47
|
+
| Severity | Критерий назначения |
|
|
48
|
+
|----------|---------------------|
|
|
49
|
+
| 🔴 Critical | RCE, auth bypass, data corruption, необратимый финансовый риск |
|
|
50
|
+
| 🟠 High | Падение production, privilege escalation, утечка данных |
|
|
51
|
+
| 🟡 Medium | Деградация производительности или поддерживаемости без immediate outage |
|
|
52
|
+
| 🟢 Low | Стиль, читаемость, слабое нарушение конвенции |
|
|
53
|
+
|
|
54
|
+
Правило: severity = impact × exploitability × blast radius. Одинаковый паттерн → одинаковый severity между аудитами.
|
|
55
|
+
|
|
56
|
+
## Чеклист
|
|
57
|
+
|
|
58
|
+
| Check ID | Проверка |
|
|
59
|
+
|----------|----------|
|
|
60
|
+
| DEP-01 | Docker images используют pinned versions (нет :latest) |
|
|
61
|
+
| DEP-02 | Контейнеры запускаются от непривилегированного пользователя (USER nonroot) |
|
|
62
|
+
| DEP-03 | Multi-stage build: финальный образ без инструментов сборки и dev-артефактов |
|
|
63
|
+
| DEP-04 | .dockerignore исключает артефакты сборки/зависимости, VCS-каталог и секреты |
|
|
64
|
+
| DEP-05 | HEALTHCHECK определён в Dockerfile |
|
|
65
|
+
| DEP-06 | Секреты не hardcoded в Dockerfile (нет в ENV) |
|
|
66
|
+
| DEP-07 | .env исключён из VCS |
|
|
67
|
+
| DEP-08 | .env.example документирует все переменные окружения |
|
|
68
|
+
| DEP-09 | Окружение переключено в production-режим: dev-артефакты выключены в проде |
|
|
69
|
+
| DEP-10 | Детерминированная установка по локфайлу с проверкой целостности |
|
|
70
|
+
| DEP-11 | Ограничения ресурсов контейнера определены (CPU limits, Memory limits) |
|
|
71
|
+
| DEP-12 | Возможность запуска с read-only root filesystem проверена |
|
|
72
|
+
|
|
73
|
+
## Правила верификации
|
|
74
|
+
|
|
75
|
+
1. **Только чеклист**: оценивай ТОЛЬКО проверки выше. Не добавляй новые.
|
|
76
|
+
2. **Явная верификация = PASS**: ставь `✅ PASS` только если явно проверил механизм (нашёл схему, конфиг, guard) и подтвердил отсутствие нарушения — укажи что именно проверено.
|
|
77
|
+
3. **Нет доказательства = UNVERIFIED**: не можешь указать `файл:строка` ни для нарушения, ни для подтверждения — ставь `🔍 UNVERIFIED`.
|
|
78
|
+
4. **Baseline приоритетен**: check_id есть в `docs/audit-baseline.yml` → `⏸ ACCEPTED`.
|
|
79
|
+
5. **Только 🔴/🟠 FAIL требуют решения**: 🟡/🟢 — решение необязательно.
|
|
80
|
+
|
|
81
|
+
## Evidence Quality Rules
|
|
82
|
+
|
|
83
|
+
Любой `❌ FAIL` обязан содержать:
|
|
84
|
+
- Точный `file:line`
|
|
85
|
+
- Минимальный код-фрагмент (1–3 строки)
|
|
86
|
+
- Causal chain: почему именно это нарушение → какой риск возникает
|
|
87
|
+
|
|
88
|
+
Запрещено:
|
|
89
|
+
- Предполагать runtime behavior без evidence в коде
|
|
90
|
+
- Предполагать prod-конфигурацию по dev-конфигу
|
|
91
|
+
- Предполагать отсутствие middleware без проверки всей router chain
|
|
92
|
+
- Если вывод основан на предположении — только `🔍 UNVERIFIED`
|
|
93
|
+
|
|
94
|
+
## Language Rule
|
|
95
|
+
|
|
96
|
+
Результаты аудита должны быть написаны простым и понятным языком. Избегай сложных терминов, жаргона и абстрактных понятий без необходимости. Общепринятые технические термины (Docker, HTTP, API, JSON, URL) допустимы. Описывай проблемы так, чтобы они были понятны разработчику любого уровня, а не только узкому специалисту в данной области.
|
|
97
|
+
|
|
98
|
+
## Baseline
|
|
99
|
+
|
|
100
|
+
До анализа:
|
|
101
|
+
```bash
|
|
102
|
+
if [ ! -f ./docs/audit-baseline.yml ]; then
|
|
103
|
+
mkdir -p ./docs
|
|
104
|
+
cp ./skills/audit/audit-baseline-template.yml ./docs/audit-baseline.yml 2>/dev/null || \
|
|
105
|
+
printf "accepted: []\n" > ./docs/audit-baseline.yml
|
|
106
|
+
fi
|
|
107
|
+
cat ./docs/audit-baseline.yml
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Контекст анализа
|
|
111
|
+
|
|
112
|
+
> Примеры ниже — иллюстративные. Конкретные инструменты, идиомы и анти-паттерны
|
|
113
|
+
> сборки/деплоя для текущего рантайма бери из загруженного профиля
|
|
114
|
+
> (`stacks/<runtime>.md`, секции Idioms/Anti-patterns/Check-ID hints по префиксу
|
|
115
|
+
> `DEP-`). Node: `npm ci`/`package-lock.json`, `NODE_ENV`, `node_modules`.
|
|
116
|
+
> Go: builder→distroless, `go.mod`+`go.sum`, `CGO_ENABLED=0`, нет `net/http/pprof`.
|
|
117
|
+
|
|
118
|
+
**DEP-01 — Pinned versions:**
|
|
119
|
+
- Базовый образ `:latest` без pinning версии (непредсказуемые обновления)
|
|
120
|
+
- Тег `:alpine` без конкретной версии
|
|
121
|
+
- Digest-based pinning отсутствует для критичных образов
|
|
122
|
+
|
|
123
|
+
**DEP-02 — Непривилегированный пользователь:**
|
|
124
|
+
- Запуск контейнера как root без переключения на non-root (Node: `USER node`; Go: distroless `nonroot`)
|
|
125
|
+
- Отсутствие создания non-root пользователя перед переключением (или образа со встроенным nonroot)
|
|
126
|
+
|
|
127
|
+
**DEP-03 — Multi-stage build: финальный образ без инструментов сборки и dev-артефактов:**
|
|
128
|
+
- Отсутствие multi-stage build (инструменты сборки/dev-зависимости в финальном образе)
|
|
129
|
+
- Node: `devDependencies` устанавливаются в production stage
|
|
130
|
+
- Go: компилятор/тесты в финальном образе вместо `builder → distroless`
|
|
131
|
+
- Build artifacts не копируются из builder stage
|
|
132
|
+
|
|
133
|
+
**DEP-04 — .dockerignore:**
|
|
134
|
+
- Нет `.dockerignore` или он не исключает зависимости/артефакты сборки (Node: `node_modules`; Go: локальный `vendor/`, build-кэш) и VCS-каталог `.git`
|
|
135
|
+
- `.env` и прочие секреты не исключены из Docker build context
|
|
136
|
+
- Тесты и документация попадают в production образ
|
|
137
|
+
|
|
138
|
+
**DEP-05 — HEALTHCHECK:**
|
|
139
|
+
- HEALTHCHECK отсутствует в Dockerfile
|
|
140
|
+
- Health check endpoint не существует в приложении
|
|
141
|
+
|
|
142
|
+
**DEP-06 — Секреты не в Dockerfile ENV:**
|
|
143
|
+
- Secrets в `ENV` директивах Dockerfile (видны в docker inspect и слоях образа)
|
|
144
|
+
- Credentials в `ARG` без использования build secrets (`--secret`)
|
|
145
|
+
|
|
146
|
+
**DEP-07 — .env исключён из VCS:**
|
|
147
|
+
- `.env` файл с реальными credentials закоммичен в репозиторий
|
|
148
|
+
- Отсутствие `.env*` в `.gitignore`
|
|
149
|
+
|
|
150
|
+
**DEP-08 — .env.example документирует переменные:**
|
|
151
|
+
- `.env.example` отсутствует
|
|
152
|
+
- `.env.example` содержит реальные credentials
|
|
153
|
+
- Не все обязательные переменные задокументированы
|
|
154
|
+
|
|
155
|
+
**DEP-09 — Окружение переключено в production-режим:**
|
|
156
|
+
- Dev-артефакты не выключены в проде: debug-эндпоинты, verbose-логи, dev-зависимости
|
|
157
|
+
- Node: `NODE_ENV` не выставлен или `development` в prod образе (ведёт к загрузке devDependencies в runtime)
|
|
158
|
+
- Go: нет признаков prod-режима (нет `APP_ENV`/собственного флага), `net/http/pprof` и debug-роуты доступны в проде, нет `-ldflags "-s -w"`, нет `CGO_ENABLED=0`
|
|
159
|
+
|
|
160
|
+
**DEP-10 — Детерминированная установка по локфайлу с проверкой целостности:**
|
|
161
|
+
- Node: `npm install` вместо `npm ci` (не детерминированная, медленнее); отсутствие `package-lock.json`
|
|
162
|
+
- Go: `go.mod`/`go.sum` не закоммичены; в Dockerfile `go get` вместо `go mod download` по локфайлу; нет `GOFLAGS=-mod=readonly` / `go mod verify`
|
|
163
|
+
|
|
164
|
+
**Ограничения ресурсов:**
|
|
165
|
+
- `docker-compose.yml` без `deploy.resources.limits.memory` и `cpus`
|
|
166
|
+
- Kubernetes Deployment без `resources.limits` в контейнере
|
|
167
|
+
- Нет ограничений → один контейнер с memory leak роняет весь хост
|
|
168
|
+
- Go-доп.: при memory-лимите контейнера выставить `GOMEMLIMIT`/`GOMAXPROCS` под cgroup-квоты (иначе GC видит память/CPU хоста)
|
|
169
|
+
|
|
170
|
+
**Read-only filesystem:**
|
|
171
|
+
- Контейнер без `read_only: true` (docker-compose) или `readOnlyRootFilesystem: true` (K8s)
|
|
172
|
+
- Если приложение пишет во временные файлы — проверить наличие tmpfs mount для `/tmp`
|
|
173
|
+
|
|
174
|
+
## Формат вывода
|
|
175
|
+
|
|
176
|
+
| Check ID | Проверка | Статус | Уверенность | Доказательство | Решение | Исправлено |
|
|
177
|
+
|----------|----------|--------|-------------|----------------|---------|------------|
|
|
178
|
+
| DEP-01 | Docker images используют pinned versions (нет :latest) | ✅ PASS | High | `Dockerfile:1` — pinned version указана | — | — |
|
|
179
|
+
| DEP-02 | Контейнеры запускаются от непривилегированного пользователя (USER nonroot) | ❌ FAIL 🟠 | High | `Dockerfile:12` | **1. Добавить `RUN addgroup -S app && adduser -S app -G app` и `USER app`** \\ 2. Использовать образ со встроенным nonroot (Node: node:alpine; Go: distroless nonroot) \\ 3. Добавить `USER node` если базовый образ node | Нет |
|
|
180
|
+
| DEP-05 | HEALTHCHECK определён в Dockerfile | ⏸ ACCEPTED | Medium | — | В baseline: health check управляется Kubernetes liveness probe | — |
|
|
181
|
+
|
|
182
|
+
Статусы: `✅ PASS` / `❌ FAIL 🔴` / `❌ FAIL 🟠` / `❌ FAIL 🟡` / `❌ FAIL 🟢` / `⏸ ACCEPTED` / `🔍 UNVERIFIED`
|
|
183
|
+
|
|
184
|
+
Уверенность: `High` — проверил несколько ключевых файлов, паттерн очевиден / `Medium` — проверил выборочно, паттерн вероятен / `Low` — ограниченный контекст, полная уверенность невозможна
|
|
185
|
+
|
|
186
|
+
Для `❌ FAIL`: ровно 3 варианта решения, разделитель `\\`, вариант 1 жирным.
|
|
187
|
+
|
|
188
|
+
`Исправлено`: FAIL → `Нет` (разработчик меняет на `✅ Да` вручную после фикса). PASS / ACCEPTED / UNVERIFIED → `—`.
|
|
189
|
+
|
|
190
|
+
Требования к решениям:
|
|
191
|
+
- Взаимно исключающие (не перефразировки одного и того же)
|
|
192
|
+
- Соответствуют текущему стеку проекта (не предлагать смену фреймворка)
|
|
193
|
+
- Не требуют переписать всю систему — realistic migration cost
|
|
194
|
+
- Вариант 3 может быть «оставить, задокументировать причину» при наличии обоснования
|
|
195
|
+
|
|
196
|
+
В конце отчёта добавь раздел покрытия:
|
|
197
|
+
```
|
|
198
|
+
## Audit Coverage
|
|
199
|
+
Проверено: src/module1/**, src/module2/**
|
|
200
|
+
Пропущено: scripts/**, migrations/**, tests/**
|
|
201
|
+
Файлов проверено: N | Пропущено: N
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Если все PASS — выведи: `✅ Конфигурация сборки и деплоя в порядке.`
|
|
205
|
+
|
|
206
|
+
## Сохранение результатов
|
|
207
|
+
|
|
208
|
+
1. Найди папку сессии:
|
|
209
|
+
```bash
|
|
210
|
+
ls -dt ./docs/audits/[0-9]*/ 2>/dev/null | head -1 | sed 's|/$||'
|
|
211
|
+
```
|
|
212
|
+
Если пусто — создай: `mkdir -p ./docs/audits/$(date +"%Y-%m-%d_%H-%M")`
|
|
213
|
+
2. Сохрани через Write: `<AUDIT_DIR>/audit-deployment.md`
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
# Audit Report: Build & Deployment Configuration — <YYYY-MM-DD HH:MM>
|
|
217
|
+
<таблица>
|
|
218
|
+
```
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: audit-docs
|
|
3
|
+
description: >
|
|
4
|
+
Аудит документации: расхождение README/инструкций с реальным кодом, битые ссылки,
|
|
5
|
+
рассинхрон env-переменных, комментарии и JSDoc, противоречащие сигнатурам, устаревшие
|
|
6
|
+
упоминания удалённых сущностей. Запускай при /audit-docs или запросе проверить документацию.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Правило применимости (Relevance Rule)
|
|
10
|
+
|
|
11
|
+
Применим к любому проекту, где есть документация (README, `docs/**`, JSDoc, инструкции запуска) или комментарии в коде. Для проектов без документации вообще — проверяй только DOC-01 (минимум для онбординга) и DOC-04 (комментарии).
|
|
12
|
+
|
|
13
|
+
**Фокус — только верифицируемые расхождения.** Этот аудит НЕ оценивает «достаточно ли документации» субъективно. `❌ FAIL` ставится только когда документация **противоречит** коду или ссылается на то, чего нет — и это доказуемо `file:line`. «Хорошо бы добавить описание» без конкретного противоречия — не находка.
|
|
14
|
+
|
|
15
|
+
**Граница с соседними аудитами** (чтобы не дублировать находки):
|
|
16
|
+
- `audit-api-contracts` — владеет «документация API vs реализация» (эндпоинты, формы ответов, OpenAPI/GraphQL-схема). REST/GraphQL-контракты отдавай туда.
|
|
17
|
+
- `audit-yagni` (YAGNI-05) — владеет устаревшими TODO/FIXME без прогресса. Здесь TODO не проверяем.
|
|
18
|
+
- `audit-naming` — владеет самодокументирующимися именами. Здесь не оцениваем «понятность имён».
|
|
19
|
+
- `audit-deployment` (DEP-08) — владеет полнотой `.env.example`. DOC-02 фокусируется на **рассинхроне** «код ↔ документация», а не на наличии файла.
|
|
20
|
+
|
|
21
|
+
## Runtime Detection & Stack Profile
|
|
22
|
+
|
|
23
|
+
Этот аудит стек-агностичен: проверки сформулированы нейтрально, а конкретика
|
|
24
|
+
(инструменты, идиомы, анти-паттерны, примеры) берётся из профиля стека.
|
|
25
|
+
|
|
26
|
+
1. **Профиль передан контекстом?** Если оркестратор `/audit` передал
|
|
27
|
+
`runtime=<id>` и/или содержимое профиля — используй его, шаги 2–3 пропусти.
|
|
28
|
+
|
|
29
|
+
2. **Иначе определи РОВНО ОДИН рантайм** этого каталога:
|
|
30
|
+
```bash
|
|
31
|
+
if [ -f package.json ]; then echo "runtime=node"
|
|
32
|
+
elif [ -f go.mod ]; then echo "runtime=go"
|
|
33
|
+
elif [ -f pyproject.toml ] || [ -f requirements.txt ] || [ -f setup.py ]; then echo "runtime=python"
|
|
34
|
+
elif [ -f Cargo.toml ]; then echo "runtime=rust"
|
|
35
|
+
elif [ -f pom.xml ] || ls build.gradle* settings.gradle* >/dev/null 2>&1; then echo "runtime=java"
|
|
36
|
+
else echo "runtime=generic"; fi
|
|
37
|
+
```
|
|
38
|
+
Один запуск = один рантайм; не миксуй backend и frontend. Если найдено
|
|
39
|
+
несколько маркеров (монорепо) — выбери соответствующий текущему scope/анализируемым
|
|
40
|
+
файлам и зафиксируй выбор в разделе Audit Coverage.
|
|
41
|
+
|
|
42
|
+
3. **Загрузи профиль** через Read: `./skills/audit/stacks/<runtime>.md`
|
|
43
|
+
(fallback `./skills/audit/stacks/_generic.md`, если файл не найден).
|
|
44
|
+
|
|
45
|
+
Дальше используй профиль:
|
|
46
|
+
- **Инструменты** — из секции «Tooling by category» профиля (раздел
|
|
47
|
+
«Инструментальная поддержка» ниже ссылается на категории, а не на команды).
|
|
48
|
+
- **Ожидания PASS** — из «Idioms»; **формулировки FAIL** — из «Anti-patterns».
|
|
49
|
+
- **Точечные подсказки** — из «Check-ID hints» по префиксу `DOC-`.
|
|
50
|
+
- Если профиль `tier: general` или `runtime=generic` → стек-специфичные находки
|
|
51
|
+
без однозначного evidence помечай `🔍 UNVERIFIED`, а не `❌ FAIL`. Проверки,
|
|
52
|
+
чей механизм в рантайме отсутствует, помечай `N/A`.
|
|
53
|
+
|
|
54
|
+
## Severity Guide
|
|
55
|
+
|
|
56
|
+
| Severity | Критерий назначения |
|
|
57
|
+
|----------|---------------------|
|
|
58
|
+
| 🔴 Critical | Документация направляет на небезопасное действие: инструкция отключить security-механизм, опубликованный реальный секрет «для примера», команда с разрушительным побочным эффектом без предупреждения |
|
|
59
|
+
| 🟠 High | Инструкция, ломающая онбординг/деплой: неверная команда установки/запуска, отсутствующая обязательная env-переменная, из-за которой прод падает или конфигурируется неверно |
|
|
60
|
+
| 🟡 Medium | Дрейф: README/комментарий/JSDoc противоречит текущему коду, битые внутренние ссылки, упоминание удалённых сущностей |
|
|
61
|
+
| 🟢 Low | Незначительная нехватка: публичный экспорт без doc-комментария, мелкая неактуальность без риска |
|
|
62
|
+
|
|
63
|
+
Правило: severity = impact × вероятность ввести разработчика/оператора в заблуждение × blast radius. Одинаковый паттерн → одинаковый severity между аудитами.
|
|
64
|
+
|
|
65
|
+
## Чеклист
|
|
66
|
+
|
|
67
|
+
| Check ID | Проверка |
|
|
68
|
+
|----------|----------|
|
|
69
|
+
| DOC-01 | README/онбординг документирует установку, запуск, тесты, сборку; команды совпадают с манифестом задач проекта (package.json scripts / Makefile / Taskfile) |
|
|
70
|
+
| DOC-02 | Env-переменные синхронизированы: каждая используемая в коде переменная задокументирована, нет задокументированных, но неиспользуемых |
|
|
71
|
+
| DOC-03 | Внутренние ссылки и пути в Markdown-документации ведут на существующие файлы и секции |
|
|
72
|
+
| DOC-04 | Комментарии и JSDoc/docstring не противоречат коду (сигнатура, имена параметров, типы, описанное поведение) |
|
|
73
|
+
| DOC-05 | Публичная поверхность (экспортируемое API библиотеки/пакета) имеет doc-комментарий назначения и параметров |
|
|
74
|
+
| DOC-06 | Проектная/архитектурная документация не ссылается на удалённые или переименованные сущности и неактуальные факты |
|
|
75
|
+
|
|
76
|
+
## Правила верификации
|
|
77
|
+
|
|
78
|
+
1. **Только чеклист**: оценивай ТОЛЬКО проверки выше. Не добавляй новые.
|
|
79
|
+
2. **Расхождение, не отсутствие**: `❌ FAIL` валиден только при доказуемом противоречии «документация ↔ код» или ссылке на несуществующее. Субъективное «мало документации» — не FAIL.
|
|
80
|
+
3. **Два якоря на находку**: каждый FAIL обязан указывать И место в документации (`file:line`), И место в коде, которое его опровергает (`file:line`).
|
|
81
|
+
4. **Явная верификация = PASS**: ставь `✅ PASS`, только если сверил документ с кодом и подтвердил соответствие — укажи что именно сверено.
|
|
82
|
+
5. **Нет доказательства = UNVERIFIED**: не можешь указать оба якоря — ставь `🔍 UNVERIFIED`.
|
|
83
|
+
6. **Baseline приоритетен**: check_id есть в `docs/audit-baseline.yml` → `⏸ ACCEPTED`.
|
|
84
|
+
7. **Только 🔴/🟠 FAIL требуют решения**: 🟡/🟢 — решение необязательно.
|
|
85
|
+
|
|
86
|
+
## Evidence Quality Rules
|
|
87
|
+
|
|
88
|
+
Любой `❌ FAIL` обязан содержать:
|
|
89
|
+
- Якорь в документации: `file:line` + цитата утверждения (1–2 строки)
|
|
90
|
+
- Якорь в коде: `file:line`, опровергающий утверждение
|
|
91
|
+
- Causal chain: почему расхождение → кого и как введёт в заблуждение (разработчик при онбординге / оператор при деплое / читатель API)
|
|
92
|
+
|
|
93
|
+
Запрещено:
|
|
94
|
+
- Считать FAIL отсутствие комментария там, где код самоочевиден (это не противоречие)
|
|
95
|
+
- Проверять внешние URL на доступность (сеть нестабильна) — только внутренние ссылки/пути и якоря внутри репозитория
|
|
96
|
+
- Предполагать, что команда/переменная «вероятно устарела» без сверки с кодом — только `🔍 UNVERIFIED`
|
|
97
|
+
- Дублировать находки, принадлежащие `audit-api-contracts`/`audit-yagni`/`audit-naming` (см. границы выше)
|
|
98
|
+
|
|
99
|
+
## Language Rule
|
|
100
|
+
|
|
101
|
+
Результаты аудита должны быть написаны простым и понятным языком. Избегай сложных терминов, жаргона и абстрактных понятий без необходимости. Общепринятые технические термины (Docker, HTTP, API, JSON, URL) допустимы. Описывай проблемы так, чтобы они были понятны разработчику любого уровня, а не только узкому специалисту в данной области.
|
|
102
|
+
|
|
103
|
+
## Baseline
|
|
104
|
+
|
|
105
|
+
До анализа:
|
|
106
|
+
```bash
|
|
107
|
+
if [ ! -f ./docs/audit-baseline.yml ]; then
|
|
108
|
+
mkdir -p ./docs
|
|
109
|
+
cp ./skills/audit/audit-baseline-template.yml ./docs/audit-baseline.yml 2>/dev/null || \
|
|
110
|
+
printf "accepted: []\n" > ./docs/audit-baseline.yml
|
|
111
|
+
fi
|
|
112
|
+
cat ./docs/audit-baseline.yml
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Контекст анализа
|
|
116
|
+
|
|
117
|
+
**DOC-01 — Инструкции совпадают с реальностью:**
|
|
118
|
+
- README ссылается на скрипт/команду, которой нет в манифесте задач проекта (package.json scripts / Makefile / Taskfile)
|
|
119
|
+
- Документированы шаги установки с неверным менеджером пакетов или версией рантайма (несовпадение с `engines`/lock-файлом)
|
|
120
|
+
- Отсутствует базовый онбординг (как установить / запустить / прогнать тесты) при наличии этих скриптов в проекте
|
|
121
|
+
|
|
122
|
+
**DOC-02 — Синхронизация env-переменных:**
|
|
123
|
+
- Переменная используется в коде, но отсутствует в `.env.example`/README — оператор не узнает о ней
|
|
124
|
+
- Переменная задокументирована, но больше нигде не читается (устаревшая инструкция)
|
|
125
|
+
- Описание переменной противоречит коду (дефолт, формат, обязательность)
|
|
126
|
+
- Синтаксис извлечения env-переменных из кода бери из профиля стека (`process.env` / `import.meta.env` / `os.Getenv`)
|
|
127
|
+
|
|
128
|
+
**DOC-03 — Валидные ссылки и пути:**
|
|
129
|
+
- Относительная ссылка в Markdown ведёт на несуществующий файл
|
|
130
|
+
- Якорь (`#section`) указывает на отсутствующий заголовок
|
|
131
|
+
- Путь к файлу/папке в инструкции не существует в репозитории
|
|
132
|
+
|
|
133
|
+
**DOC-04 — Комментарии не лгут:**
|
|
134
|
+
- JSDoc/TSDoc `@param`/`@returns` не совпадает с фактической сигнатурой (имя, число, тип параметров)
|
|
135
|
+
- Комментарий описывает поведение, противоположное коду («возвращает null, если...» — а код кидает исключение)
|
|
136
|
+
- Docstring/комментарий ссылается на параметр/шаг, которого в функции уже нет
|
|
137
|
+
|
|
138
|
+
**DOC-05 — Документация публичной поверхности:**
|
|
139
|
+
- Применять ТОЛЬКО если проект является публикуемой библиотекой/пакетом (по манифесту проекта)
|
|
140
|
+
- Экспортируемая публичная функция/класс/тип без doc-комментария назначения
|
|
141
|
+
- Для приложений (не публикуемая библиотека) — DOC-05 = `N/A`, не FAIL
|
|
142
|
+
|
|
143
|
+
**DOC-06 — Актуальность проектной документации:**
|
|
144
|
+
- Архитектурный документ описывает модуль/сервис/эндпоинт, удалённый или переименованный в коде
|
|
145
|
+
- Диаграмма/схема упоминает технологию, которой больше нет в зависимостях
|
|
146
|
+
- Версия в документации расходится с `package.json`/тегом (если документация декларирует версию)
|
|
147
|
+
|
|
148
|
+
## Инструментальная поддержка
|
|
149
|
+
|
|
150
|
+
Env-переменные — код vs документация (DOC-02): извлеки имена env-переменных из кода
|
|
151
|
+
инструментом категории **env-extraction** из профиля стека (секция «Tooling by
|
|
152
|
+
category»; синтаксис зависит от рантайма — Node: `process.env`/`import.meta.env`;
|
|
153
|
+
Go: `os.Getenv`). Сравни полученный список с задокументированными переменными
|
|
154
|
+
(`.env.example`/README); разница между списками — кандидаты в DOC-02. Верифицируй
|
|
155
|
+
каждую вручную (бывают переменные из CI/инфраструктуры, не из `.env`).
|
|
156
|
+
|
|
157
|
+
Команды README vs манифест задач (DOC-01): возьми список задач/скриптов из
|
|
158
|
+
**манифеста задач проекта** (по профилю стека: `package.json` scripts / `Makefile` /
|
|
159
|
+
`Taskfile`). Команды, упомянутые в README, сверь с этим манифестом — команда из
|
|
160
|
+
README, которой нет в манифесте, → кандидат в DOC-01.
|
|
161
|
+
|
|
162
|
+
Внутренние ссылки в Markdown (DOC-03): извлеки относительные ссылки `[...](./path)` и проверь существование путей через `Read`/`ls`. Внешние `http(s)://`-ссылки НЕ проверяй на доступность.
|
|
163
|
+
|
|
164
|
+
## Формат вывода
|
|
165
|
+
|
|
166
|
+
| Check ID | Проверка | Статус | Уверенность | Доказательство | Решение | Исправлено |
|
|
167
|
+
|----------|----------|--------|-------------|----------------|---------|------------|
|
|
168
|
+
| DOC-01 | README документирует установку/запуск/тесты, команды совпадают со scripts | ❌ FAIL 🟠 | High | `README.md:24` — `npm run start:dev`; в `package.json` есть только `dev` | **1. Исправить README на `npm run dev`** \\ 2. Добавить алиас `start:dev` в scripts \\ 3. Сгенерировать раздел команд из scripts автоматически | Нет |
|
|
169
|
+
| DOC-02 | Env-переменные синхронизированы | ❌ FAIL 🟠 | High | `src/config.ts:9` читает `REDIS_URL`; нет в `.env.example` | **1. Добавить `REDIS_URL` в `.env.example` с описанием** \\ 2. Валидировать env при старте (zod/envalid) \\ 3. Удалить чтение переменной, если она не нужна | Нет |
|
|
170
|
+
| DOC-04 | Комментарии и JSDoc не противоречат коду | ❌ FAIL 🟡 | Medium | `src/user.ts:40` JSDoc `@returns User`; функция возвращает `User | null` | **1. Поправить `@returns` на `User \| null`** \\ 2. Удалить устаревший JSDoc \\ 3. Включить `eslint-plugin-jsdoc` для авто-проверки | Нет |
|
|
171
|
+
| DOC-05 | Публичная поверхность задокументирована | ✅ PASS | Medium | по манифесту — приложение, не публикуемая библиотека → N/A | — | — |
|
|
172
|
+
|
|
173
|
+
Статусы: `✅ PASS` / `❌ FAIL 🔴` / `❌ FAIL 🟠` / `❌ FAIL 🟡` / `❌ FAIL 🟢` / `⏸ ACCEPTED` / `🔍 UNVERIFIED` / `N/A`
|
|
174
|
+
|
|
175
|
+
Уверенность: `High` — сверил утверждение документации с кодом, расхождение однозначно / `Medium` — расхождение вероятно, контекст проверен выборочно / `Low` — ограниченный контекст, полная уверенность невозможна
|
|
176
|
+
|
|
177
|
+
Для `❌ FAIL`: ровно 3 варианта решения, разделитель `\\`, вариант 1 жирным.
|
|
178
|
+
|
|
179
|
+
`Исправлено`: FAIL → `Нет` (разработчик меняет на `✅ Да` вручную после фикса). PASS / ACCEPTED / UNVERIFIED / N/A → `—`.
|
|
180
|
+
|
|
181
|
+
Требования к решениям:
|
|
182
|
+
- Взаимно исключающие (не перефразировки одного и того же)
|
|
183
|
+
- Минимум один вариант — «исправить документ», минимум один — «исправить/удалить код или автоматизировать сверку»
|
|
184
|
+
- Реалистичная стоимость, без «переписать всю документацию»
|
|
185
|
+
- Вариант 3 может быть «удалить устаревший раздел/комментарий», если он больше не нужен
|
|
186
|
+
|
|
187
|
+
В конце отчёта добавь раздел покрытия:
|
|
188
|
+
```
|
|
189
|
+
## Audit Coverage
|
|
190
|
+
Проверено: README.md, docs/**, src/**/*.ts (JSDoc), .env.example
|
|
191
|
+
Пропущено: CHANGELOG.md (auto-generated), node_modules/**
|
|
192
|
+
Файлов проверено: N | Пропущено: N
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Если все PASS — выведи: `✅ Расхождений документации с кодом не обнаружено.`
|
|
196
|
+
|
|
197
|
+
## Сохранение результатов
|
|
198
|
+
|
|
199
|
+
1. Найди папку сессии:
|
|
200
|
+
```bash
|
|
201
|
+
ls -dt ./docs/audits/[0-9]*/ 2>/dev/null | head -1 | sed 's|/$||'
|
|
202
|
+
```
|
|
203
|
+
Если пусто — создай: `mkdir -p ./docs/audits/$(date +"%Y-%m-%d_%H-%M")`
|
|
204
|
+
2. Сохрани через Write: `<AUDIT_DIR>/audit-docs.md`
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
# Audit Report: Documentation — <YYYY-MM-DD HH:MM>
|
|
208
|
+
<таблица>
|
|
209
|
+
```
|