@nitra/cursor 1.13.25 → 1.13.26

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.
@@ -78,7 +78,7 @@ if [ -f "$STATE_FILE" ]; then
78
78
  fi
79
79
 
80
80
  THRESHOLD="${ADR_NORMALIZE_THRESHOLD:-30}"
81
- BATCH_SIZE="${ADR_NORMALIZE_BATCH:-30}"
81
+ BATCH_SIZE="${ADR_NORMALIZE_BATCH:-10}"
82
82
  DRY_RUN="${ADR_NORMALIZE_DRY:-0}"
83
83
 
84
84
  # Detects whether a markdown file is a draft: has YAML frontmatter with `session:` field.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@
4
4
 
5
5
  Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
6
6
 
7
+ ## [1.13.26] - 2026-05-17
8
+
9
+ ### Changed
10
+
11
+ - `security` rule: міграція з gitleaks на TruffleHog. Канонічний `lint-security` тепер `trufflehog filesystem . --no-update --exclude-paths .trufflehog-exclude --results=verified,unknown --fail`; allowlist переїхав із TOML-файлу `.gitleaks.toml` (`[extend].useDefault=true` + `[allowlist].paths`) у plain-text `.trufflehog-exclude` (regex-pattern на рядок). Bump `security.mdc` version `1.1` → `2.0`.
12
+
13
+ ### Added
14
+
15
+ - `npm/rules/security/fix/trufflehog/check.mjs` + `template/.trufflehog-exclude.snippet.txt` — JS-частина правила перевіряє існування `.trufflehog-exclude` та subset канонічних patterns через `checkTextSubset` (Rego не пасує plain-text-формату).
16
+ - `npm/rules/security/policy/lint_security_yml/` — Rego policy `security.lint_security_yml` із template `lint-security.yml.snippet.yml`; перевіряє, що `.github/workflows/lint-security.yml` містить крок з `uses: trufflesecurity/trufflehog@main`. У `security.mdc` inline-YAML замінено на template-link для single-source-of-truth (патерн із `php`/`style-lint`/`js-lint`). Workflow обовʼязковий (`target.json: required=true` + `missingMessage`), у корені cursor створено `.github/workflows/lint-security.yml` за каноном.
17
+
18
+ ### Removed
19
+
20
+ - `npm/rules/security/fix/gitleaks/` + `npm/rules/security/policy/gitleaks/` (концерн gitleaks повністю видалено разом з Rego policy `security.gitleaks`).
21
+ - Кореневий `.gitleaks.toml` (замінено на `.trufflehog-exclude`).
22
+
7
23
  ## [1.13.25] - 2026-05-17
8
24
 
9
25
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "1.13.25",
3
+ "version": "1.13.26",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
package/rules/adr/adr.mdc CHANGED
@@ -35,7 +35,7 @@ Stop-hook `normalize-decisions.sh` спрацьовує на тому самом
35
35
 
36
36
  - Виходить миттєво, якщо чернеток (`session:` у frontmatter) менше ніж **`ADR_NORMALIZE_THRESHOLD`** (default 30).
37
37
  - Виходить миттєво, якщо від попередньої спроби пройшло менше **`ADR_NORMALIZE_MIN_INTERVAL_HOURS`** годин (default 6) — щоб не крутитися щоразу, коли поріг постійний.
38
- - Бере не більше **`ADR_NORMALIZE_BATCH`** чернеток (default 30, найстарші за іменем-timestamp), формує один промпт LLM і чекає JSON-відповідь зі списком операцій.
38
+ - Бере не більше **`ADR_NORMALIZE_BATCH`** чернеток (default 10, найстарші за іменем-timestamp), формує один промпт LLM і чекає JSON-відповідь зі списком операцій.
39
39
  - Виходить миттєво, якщо репозиторій у стані `MERGE_HEAD` / `rebase-*` — небезпечно правити файли посеред конфлікту.
40
40
  - Виходить миттєво, якщо інший normalize-запуск тримає `flock` на `.claude/hooks/.normalize.lock` (тільки де `flock` доступний).
41
41
 
@@ -60,7 +60,7 @@ LLM повертає масив операцій:
60
60
  | Змінна | Default | Призначення |
61
61
  | --- | --- | --- |
62
62
  | `ADR_NORMALIZE_THRESHOLD` | `30` | Поріг чернеток для запуску фази. |
63
- | `ADR_NORMALIZE_BATCH` | `30` | Максимум чернеток у одному виклику LLM. |
63
+ | `ADR_NORMALIZE_BATCH` | `10` | Максимум чернеток у одному виклику LLM. |
64
64
  | `ADR_NORMALIZE_MIN_INTERVAL_HOURS` | `6` | Мінімум між спробами (навіть якщо поріг). |
65
65
  | `ADR_NORMALIZE_DRY` | `0` | `1` — лише лог запланованих операцій, без змін на диску. |
66
66
  | `ADR_NORMALIZE_MODEL` | `sonnet` | Модель для `claude -p`. |
@@ -0,0 +1,45 @@
1
+ /**
2
+ * FS-частина правила `security`.
3
+ *
4
+ * Перевіряє:
5
+ * - наявність `package.json` (структуру валідує policy security.package_json);
6
+ * - наявність `.trufflehog-exclude` у корені та subset канонічних patterns
7
+ * (text-subset, бо `.trufflehog-exclude` — plain text, не структурований).
8
+ */
9
+ import { existsSync } from 'node:fs'
10
+ import { readFile } from 'node:fs/promises'
11
+ import { dirname, join } from 'node:path'
12
+ import { fileURLToPath } from 'node:url'
13
+
14
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
15
+ import { checkTextSubset } from '../../../../scripts/utils/template.mjs'
16
+
17
+ const HERE = dirname(fileURLToPath(import.meta.url))
18
+ const SNIPPET_PATH = join(HERE, 'template', '.trufflehog-exclude.snippet.txt')
19
+
20
+ export async function check() {
21
+ const reporter = createCheckReporter()
22
+ const { pass, fail } = reporter
23
+
24
+ if (!existsSync('package.json')) {
25
+ fail('package.json не знайдено в корені — додай (security.mdc)')
26
+ return reporter.getExitCode()
27
+ }
28
+ pass('package.json є (структуру перевіряє Rego)')
29
+
30
+ if (!existsSync('.trufflehog-exclude')) {
31
+ fail('.trufflehog-exclude не знайдено в корені — додай за каноном (security.mdc)')
32
+ return reporter.getExitCode()
33
+ }
34
+
35
+ const actual = await readFile('.trufflehog-exclude', 'utf8')
36
+ const template = await readFile(SNIPPET_PATH, 'utf8')
37
+ const errors = checkTextSubset(actual, template, {
38
+ targetPath: '.trufflehog-exclude',
39
+ source: 'security.mdc'
40
+ })
41
+ for (const msg of errors) fail(msg)
42
+ if (errors.length === 0) pass('.trufflehog-exclude містить канонічні patterns')
43
+
44
+ return reporter.getExitCode()
45
+ }
@@ -0,0 +1,6 @@
1
+ (^|/)node_modules(/|$)
2
+ (^|/)\.git(/|$)
3
+ (^|/)dist(/|$)
4
+ (^|/)build(/|$)
5
+ .*\.lock$
6
+ .*fixtures?/.*
@@ -0,0 +1,33 @@
1
+ # Перевірка `.github/workflows/lint-security.yml` (security.mdc).
2
+ #
3
+ # Канон надходить через --data: { "template": { "snippet": ... } }, побудоване
4
+ # з template/lint-security.yml.snippet.yml. З нього збирається перелік
5
+ # `uses:` action-refs security-job (виключаючи універсальні `actions/*`, які
6
+ # валідує `ga.workflow_common`).
7
+ #
8
+ # Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
9
+ package security.lint_security_yml
10
+
11
+ import rego.v1
12
+
13
+ # Очікувані action-uses із template (не-`actions/*`).
14
+ expected_uses_blob := concat("\n", [u |
15
+ some step in data.template.snippet.jobs.security.steps
16
+ u := object.get(step, "uses", "")
17
+ u != ""
18
+ not startswith(u, "actions/")
19
+ ])
20
+
21
+ # Усі `uses:` із input workflow.
22
+ all_uses_text := concat("\n", [u |
23
+ some job in object.get(input, "jobs", {})
24
+ some step in object.get(job, "steps", [])
25
+ u := object.get(step, "uses", "")
26
+ u != ""
27
+ ])
28
+
29
+ deny contains msg if {
30
+ expected_uses_blob != ""
31
+ not contains(all_uses_text, expected_uses_blob)
32
+ msg := sprintf("lint-security.yml: відсутній крок з uses %q (security.mdc)", [expected_uses_blob])
33
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://unpkg.com/@nitra/cursor/schemas/target.json",
3
+ "files": {
4
+ "single": ".github/workflows/lint-security.yml",
5
+ "required": true
6
+ },
7
+ "missingMessage": ".github/workflows/lint-security.yml не знайдено — створи за каноном security.mdc"
8
+ }
@@ -0,0 +1,31 @@
1
+ name: Lint Security
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - dev
7
+ - main
8
+
9
+ pull_request:
10
+ branches:
11
+ - dev
12
+ - main
13
+
14
+ concurrency:
15
+ group: ${{ github.ref }}-${{ github.workflow }}
16
+ cancel-in-progress: true
17
+
18
+ jobs:
19
+ security:
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ steps:
24
+ - uses: actions/checkout@v6
25
+ with:
26
+ persist-credentials: false
27
+ fetch-depth: 0
28
+
29
+ - uses: trufflesecurity/trufflehog@main
30
+ with:
31
+ extra_args: --results=verified,unknown
@@ -1,4 +1,4 @@
1
1
  {
2
- "dependencies": { "gitleaks": "глобальний CLI — не додавай у dependencies" },
3
- "devDependencies": { "gitleaks": "глобальний CLI — не додавай у devDependencies" }
2
+ "dependencies": { "trufflehog": "глобальний CLI — не додавай у dependencies" },
3
+ "devDependencies": { "trufflehog": "глобальний CLI — не додавай у devDependencies" }
4
4
  }
@@ -1 +1 @@
1
- { "scripts": { "lint-security": "gitleaks detect --no-banner" } }
1
+ { "scripts": { "lint-security": "trufflehog filesystem . --no-update --exclude-paths .trufflehog-exclude --results=verified,unknown --fail" } }
@@ -1,58 +1,37 @@
1
1
  ---
2
- description: Локальний та CI-секюріті-лінт через gitleaks — скрипт `lint-security`, `.gitleaks.toml`, інтеграція в агрегований `lint`
3
- globs: "**/.gitleaks.toml,**/package.json,**/.github/workflows/**/*.yml"
2
+ description: Локальний та CI-секюріті-лінт через TruffleHog — скрипт `lint-security`, `.trufflehog-exclude`, інтеграція в агрегований `lint`
3
+ globs: "**/.trufflehog-exclude,**/package.json,**/.github/workflows/**/*.yml"
4
4
  alwaysApply: false
5
- version: '1.1'
5
+ version: '2.0'
6
6
  ---
7
7
 
8
- [gitleaks](https://github.com/gitleaks/gitleaks) — глобальний CLI (як `shellcheck`, `conftest`); **не** додавай до `dependencies`/`devDependencies`.
8
+ [TruffleHog](https://github.com/trufflesecurity/trufflehog) — глобальний CLI (як `shellcheck`, `conftest`); **не** додавай до `dependencies`/`devDependencies`.
9
9
 
10
10
  ## Канон `package.json#scripts`
11
11
 
12
12
  - `lint-security` скрипт: [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json)
13
13
  - `lint` агрегатор повинен містити: [package.json.contains.json](./policy/package_json/template/package.json.contains.json)
14
- - Заборонено `gitleaks` у `dependencies`/`devDependencies`: [package.json.deny.json](./policy/package_json/template/package.json.deny.json)
14
+ - Заборонено `trufflehog` у `dependencies`/`devDependencies`: [package.json.deny.json](./policy/package_json/template/package.json.deny.json)
15
15
 
16
16
  **Зауваження:**
17
17
 
18
- - `gitleaks detect` — сканує робоче дерево (uncommitted + tracked); швидше і безпечніше для частого `bun run lint`, ніж `gitleaks git`.
19
- - `--no-banner` — прибирає ASCII-арт (CI-friendly).
18
+ - `trufflehog filesystem .` — сканує робоче дерево як директорію (включно з untracked/gitignored файлами); підкоманда `git file://.` лишається на CI для аудиту історії.
19
+ - `--no-update` — вимикає self-update check (CI-friendly).
20
+ - `--exclude-paths .trufflehog-exclude` — файл з regex-patterns, які треба пропускати (аналог `[allowlist].paths` із gitleaks).
21
+ - `--results=verified,unknown` — показує лише верифіковані секрети + ті, що TruffleHog не зміг перевірити (`unverified` дублікат відсіюється).
22
+ - `--fail` — exit-code `183` за наявності знахідок (потрібно, щоб `bun run lint` падав).
20
23
  - Позиція в `lint`: за конвенцією після інших `lint-*` і перед `oxfmt`.
21
24
 
22
- ## `.gitleaks.toml` (рекомендована основа)
25
+ ## `.trufflehog-exclude` (рекомендована основа)
23
26
 
24
- Канон (допускає розширення в `[allowlist].paths`): [.gitleaks.toml.snippet.toml](./fix/gitleaks/template/.gitleaks.toml.snippet.toml)
27
+ Канон (допускає розширення): [.trufflehog-exclude.snippet.txt](./fix/trufflehog/template/.trufflehog-exclude.snippet.txt)
25
28
 
26
- **Важливо:** `useDefault = true` НЕ перетирай дефолтний `rules`-масив; реальні винятки лише через `[allowlist]`.
29
+ **Важливо:** один regex-pattern на рядок, без TOML-обгортки; коментарі починаються з `#`.
27
30
 
28
- ## GitHub Actions (опційно)
31
+ ## CI: `.github/workflows/lint-security.yml`
29
32
 
30
- Окремий workflow не обовʼязковий — `lint-security` уже виконується через агрегований `lint`. Для fast-feedback окремо:
33
+ Workflow обовʼязковий — забезпечує незалежний скан секретів на push/PR (агрегований `lint` локально + окремий fail-fast job на CI).
31
34
 
32
- ```yaml title=".github/workflows/lint-security.yml"
33
- name: Lint Security
35
+ - Канон: [lint-security.yml.snippet.yml](./policy/lint_security_yml/template/lint-security.yml.snippet.yml)
34
36
 
35
- on:
36
- push:
37
- branches: [dev, main]
38
- pull_request:
39
- branches: [dev, main]
40
-
41
- concurrency:
42
- group: ${{ github.ref }}-${{ github.workflow }}
43
- cancel-in-progress: true
44
-
45
- jobs:
46
- security:
47
- runs-on: ubuntu-latest
48
- permissions:
49
- contents: read
50
- steps:
51
- - uses: actions/checkout@v6
52
- with:
53
- persist-credentials: false
54
- fetch-depth: 0
55
- - uses: gitleaks/gitleaks-action@v2
56
- ```
57
-
58
- Для повного скану git-історії потрібен `fetch-depth: 0`.
37
+ Перевіряється policy `security.lint_security_yml`: серед `uses:` має бути крок з `trufflesecurity/trufflehog@main`. Універсальні workflow-перевірки (checkout, permissions, persist-credentials) — у `ga.workflow_common`. Для повного скану історії потрібен `fetch-depth: 0`.
@@ -55,11 +55,11 @@ description: >-
55
55
  - Відкотити конкретний файл: `git checkout -- docs/adr/<file>` (для `rewrite` цього мало — треба ще `git restore --staged` і `rm` нового).
56
56
  - Відкотити весь батч: `git checkout -- docs/adr/ && git clean -f docs/adr/` (видалить і untracked rewrite-результати).
57
57
 
58
- 5. **Повторити для наступного батчу**, якщо чернеток ще багато. Кожен запуск обробляє до `ADR_NORMALIZE_BATCH` файлів (default 30, найстарші за часовою позначкою у назві).
58
+ 5. **Повторити для наступного батчу**, якщо чернеток ще багато. Кожен запуск обробляє до `ADR_NORMALIZE_BATCH` файлів (default 10, найстарші за часовою позначкою у назві).
59
59
 
60
60
  ## Tuning через ENV
61
61
 
62
- - `ADR_NORMALIZE_BATCH=10` — менший батч (менше токенів, частіші коміти).
62
+ - `ADR_NORMALIZE_BATCH=30` — більший батч (менше викликів LLM, більше токенів за раз).
63
63
  - `ADR_NORMALIZE_MODEL=opus` — інша модель `claude -p`.
64
64
  - `ADR_NORMALIZE_CURSOR_MODEL=…` — інша модель для cursor-agent fallback.
65
65
 
@@ -1,25 +0,0 @@
1
- /**
2
- * FS-частина правила `security`.
3
- *
4
- * Перевіряє:
5
- * - наявність `package.json` (структуру валідує Rego);
6
- * - контекстне pass-повідомлення для JS-концерну.
7
- *
8
- * Наявність і вміст `.gitleaks.toml` (`[extend].useDefault = true`) тепер
9
- * перевіряє policy `security.gitleaks`.
10
- */
11
- import { existsSync } from 'node:fs'
12
-
13
- import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
14
-
15
- export async function check() {
16
- const reporter = createCheckReporter()
17
- const { pass, fail } = reporter
18
- if (!existsSync('package.json')) {
19
- fail('package.json не знайдено в корені — додай (security.mdc)')
20
- return reporter.getExitCode()
21
- }
22
- pass('package.json є (структуру перевіряє Rego)')
23
- pass('.gitleaks.toml перевіряє npx @nitra/cursor check → security.gitleaks')
24
- return reporter.getExitCode()
25
- }
@@ -1,12 +0,0 @@
1
- [extend]
2
- useDefault = true
3
-
4
- [allowlist]
5
- paths = [
6
- '''(^|/)node_modules(/|$)''',
7
- '''(^|/)\.git(/|$)''',
8
- '''(^|/)dist(/|$)''',
9
- '''(^|/)build(/|$)''',
10
- '''.*\.lock$''',
11
- '''.*fixtures?/.*'''
12
- ]
@@ -1,17 +0,0 @@
1
- # Перевірка `.gitleaks.toml` для security (security.mdc).
2
- #
3
- # Канонічна мінімальна вимога: `[extend].useDefault = true`, щоб локальний
4
- # конфіг не вимикав стандартні правила gitleaks. Додаткові локальні правила
5
- # дозволені.
6
- #
7
- # Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
8
- # Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
9
- # (.cursor/rules/conftest.mdc). Лінт — `bun run lint-rego` (regal).
10
- package security.gitleaks
11
-
12
- import rego.v1
13
-
14
- deny contains msg if {
15
- object.get(object.get(input, "extend", {}), "useDefault", null) != true
16
- msg := ".gitleaks.toml: [extend].useDefault має бути true (security.mdc)"
17
- }
@@ -1,8 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@nitra/cursor/schemas/target.json",
3
- "files": {
4
- "single": ".gitleaks.toml",
5
- "required": true
6
- },
7
- "missingMessage": ".gitleaks.toml не знайдено — створи за каноном security.mdc"
8
- }