@nitra/cursor 1.13.8 → 1.13.12
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/CHANGELOG.md +60 -0
- package/package.json +1 -1
- package/rules/ga/fix/workflows/check.mjs +12 -3
- package/rules/ga/ga.mdc +18 -152
- package/rules/ga/policy/clean_ga_workflows/clean_ga_workflows.rego +38 -49
- package/rules/ga/policy/clean_ga_workflows/template/clean-ga-workflows.yml.snippet.yml +26 -0
- package/rules/ga/policy/clean_merged_branch/clean_merged_branch.rego +55 -57
- package/rules/ga/policy/clean_merged_branch/template/clean-merged-branch.yml.snippet.yml +37 -0
- package/rules/ga/policy/git_ai/git_ai.rego +28 -35
- package/rules/ga/policy/git_ai/template/git-ai.yml.snippet.yml +30 -0
- package/rules/ga/policy/lint_ga/lint_ga.rego +46 -55
- package/rules/ga/policy/lint_ga/template/lint-ga.yml.snippet.yml +35 -0
- package/rules/ga/policy/package_json/package_json.rego +9 -13
- package/rules/ga/policy/package_json/template/package.json.contains.json +1 -0
- package/rules/ga/policy/vscode_extensions/template/extensions.json.snippet.json +1 -0
- package/rules/ga/policy/vscode_extensions/vscode_extensions.rego +6 -4
- package/rules/ga/policy/vscode_settings/template/settings.json.snippet.json +1 -0
- package/rules/ga/policy/vscode_settings/vscode_settings.rego +11 -13
- package/rules/ga/policy/zizmor_yml/template/zizmor.yml.snippet.yml +5 -0
- package/rules/ga/policy/zizmor_yml/zizmor_yml.rego +16 -6
- package/rules/rego/lint/lint.mjs +5 -4
- package/rules/rego/policy/package_json/package_json.rego +8 -29
- package/rules/rego/policy/package_json/template/package.json.snippet.json +1 -0
- package/rules/rego/policy/vscode_extensions/template/extensions.json.snippet.json +1 -0
- package/rules/rego/policy/vscode_extensions/vscode_extensions.rego +7 -11
- package/rules/rego/policy/vscode_settings/template/settings.json.snippet.json +6 -0
- package/rules/rego/policy/vscode_settings/vscode_settings.rego +19 -27
- package/rules/rego/rego.mdc +10 -8
- package/rules/security/todo.MD +27 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# Перевірка `.vscode/settings.json` для GitHub Actions workflow (ga.mdc).
|
|
2
2
|
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
3
|
+
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
+
# Структура --data сформована з template/settings.json.snippet.json.
|
|
5
|
+
# Snippet — 2-рівнева мапа: <language-block-key>.<setting-key> = <expected>
|
|
6
|
+
# (VS Code-конвенція: ключі типу `[github-actions-workflow]` і `editor.defaultFormatter`
|
|
7
|
+
# — це літеральні string-keys із дужками/крапкою, не вкладені обʼєкти).
|
|
5
8
|
#
|
|
6
|
-
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
7
9
|
# Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
|
|
8
10
|
# (.cursor/rules/conftest.mdc). Лінт — `bun run lint-rego` (regal).
|
|
9
11
|
package ga.vscode_settings
|
|
@@ -11,14 +13,10 @@ package ga.vscode_settings
|
|
|
11
13
|
import rego.v1
|
|
12
14
|
|
|
13
15
|
deny contains msg if {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
block := object.get(input, "[github-actions-workflow]", null)
|
|
21
|
-
is_object(block)
|
|
22
|
-
object.get(block, "editor.defaultFormatter", null) != "oxc.oxc-vscode"
|
|
23
|
-
msg := ".vscode/settings.json: [github-actions-workflow].editor.defaultFormatter має бути \"oxc.oxc-vscode\" (ga.mdc)"
|
|
16
|
+
some block_key, expected_inner in data.template.snippet
|
|
17
|
+
inner := object.get(input, block_key, {})
|
|
18
|
+
some leaf_key, expected_value in expected_inner
|
|
19
|
+
actual := object.get(inner, leaf_key, null)
|
|
20
|
+
actual != expected_value
|
|
21
|
+
msg := sprintf(".vscode/settings.json: %s.%s має бути %q (ga.mdc)", [block_key, leaf_key, expected_value])
|
|
24
22
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Перевірка `.github/zizmor.yml` для GitHub Actions (ga.mdc).
|
|
2
2
|
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
3
|
+
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
+
# Структура --data сформована з template/zizmor.yml.snippet.yml.
|
|
5
|
+
# Канонічний шлях — `rules.unpinned-uses.config.policies."*"`; expected value
|
|
6
|
+
# (наприклад `"ref-pin"`) приходить із template, path лишається тут.
|
|
6
7
|
#
|
|
7
|
-
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
8
8
|
# Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
|
|
9
9
|
# (.cursor/rules/conftest.mdc). Лінт — `bun run lint-rego` (regal).
|
|
10
10
|
package ga.zizmor_yml
|
|
@@ -12,6 +12,16 @@ package ga.zizmor_yml
|
|
|
12
12
|
import rego.v1
|
|
13
13
|
|
|
14
14
|
deny contains msg if {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
expected := data.template.snippet.rules["unpinned-uses"].config.policies["*"]
|
|
16
|
+
policies := object.get(
|
|
17
|
+
object.get(
|
|
18
|
+
object.get(object.get(input, "rules", {}), "unpinned-uses", {}),
|
|
19
|
+
"config",
|
|
20
|
+
{},
|
|
21
|
+
),
|
|
22
|
+
"policies",
|
|
23
|
+
{},
|
|
24
|
+
)
|
|
25
|
+
object.get(policies, "*", null) != expected
|
|
26
|
+
msg := sprintf(".github/zizmor.yml: rules.unpinned-uses.config.policies[%q] має бути %q (ga.mdc)", ["*", expected])
|
|
17
27
|
}
|
package/rules/rego/lint/lint.mjs
CHANGED
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
* потрібен VS Code-розширенню `tsandall.opa` (LSP, format-on-save через `opa fmt`) — деталі в
|
|
19
19
|
* `mdc/rego.mdc`.
|
|
20
20
|
*
|
|
21
|
-
* Цілі лінту: `npm/
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* Цілі лінту: `npm/rules/` (де живуть Rego-полісі пакета `@nitra/cursor` — у
|
|
22
|
+
* `npm/rules/<id>/policy/<concern>/`). Усі три інструменти приймають один шлях
|
|
23
|
+
* і самі рекурсивно знаходять `.rego` (ігноруючи інші розширення на кшталт
|
|
24
|
+
* `target.json` чи template-фіх).
|
|
24
25
|
*/
|
|
25
26
|
import { spawnSync } from 'node:child_process'
|
|
26
27
|
import { existsSync } from 'node:fs'
|
|
@@ -30,7 +31,7 @@ import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
|
|
|
30
31
|
import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
|
|
31
32
|
|
|
32
33
|
/** Шляхи з Rego-полісі (відносно cwd). Існують не всі на ранніх стадіях — фільтруємо нижче. */
|
|
33
|
-
const LINT_TARGETS = ['npm/
|
|
34
|
+
const LINT_TARGETS = ['npm/rules']
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Друкує підказку зі встановлення `opa` (потрібен для `opa check --strict` і VS Code LSP).
|
|
@@ -1,37 +1,16 @@
|
|
|
1
1
|
# Перевірка `package.json` для rego (rego.mdc).
|
|
2
2
|
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# (бінарка з `node_modules/.bin/`) робить preflight `opa`/`regal` і прогонить
|
|
8
|
-
# `opa check --strict` → `regal lint` → опц. `conftest verify` (`@nitra/cursor lint-rego`).
|
|
9
|
-
#
|
|
10
|
-
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
3
|
+
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
+
# Структура --data сформована з template/package.json.snippet.json.
|
|
5
|
+
# Дозволяємо whitespace навколо значення (trim_space) — допуск, який мав
|
|
6
|
+
# попередній inline-варіант.
|
|
11
7
|
package rego.package_json
|
|
12
8
|
|
|
13
9
|
import rego.v1
|
|
14
10
|
|
|
15
|
-
canonical_lint_rego := "n-cursor lint-rego"
|
|
16
|
-
|
|
17
|
-
lint_rego_template := concat(" ", [
|
|
18
|
-
"package.json: scripts.lint-rego має бути %q",
|
|
19
|
-
"(зараз: %q) (rego.mdc)",
|
|
20
|
-
])
|
|
21
|
-
|
|
22
|
-
deny contains msg if {
|
|
23
|
-
scripts := object.get(input, "scripts", {})
|
|
24
|
-
not "lint-rego" in object.keys(scripts)
|
|
25
|
-
msg := concat(" ", [
|
|
26
|
-
"package.json: відсутній scripts.lint-rego — додай",
|
|
27
|
-
"\"lint-rego\": \"n-cursor lint-rego\" (rego.mdc)",
|
|
28
|
-
])
|
|
29
|
-
}
|
|
30
|
-
|
|
31
11
|
deny contains msg if {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
msg := sprintf(lint_rego_template, [canonical_lint_rego, lint_rego])
|
|
12
|
+
some script_name, expected in data.template.snippet.scripts
|
|
13
|
+
actual := object.get(object.get(input, "scripts", {}), script_name, "")
|
|
14
|
+
trim_space(actual) != expected
|
|
15
|
+
msg := sprintf("package.json: scripts.%s має бути %q (rego.mdc)", [script_name, expected])
|
|
37
16
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "scripts": { "lint-rego": "n-cursor lint-rego" } }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "recommendations": ["tsandall.opa"] }
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
# Перевірка `.vscode/extensions.json` для rego (rego.mdc).
|
|
2
2
|
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# Canonical (rego.mdc): `recommendations` має містити `tsandall.opa`.
|
|
9
|
-
#
|
|
10
|
-
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
3
|
+
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
+
# Структура --data сформована з template/extensions.json.snippet.json.
|
|
5
|
+
# `recommendations` — subset-of: кожна рекомендація з template має бути у input.
|
|
6
|
+
# Додаткові рекомендації від інших правил дозволені.
|
|
11
7
|
package rego.vscode_extensions
|
|
12
8
|
|
|
13
9
|
import rego.v1
|
|
14
10
|
|
|
15
11
|
deny contains msg if {
|
|
16
|
-
|
|
17
|
-
not
|
|
18
|
-
msg := ".vscode/extensions.json: recommendations має містити
|
|
12
|
+
some rec in data.template.snippet.recommendations
|
|
13
|
+
not rec in {r | some r in object.get(input, "recommendations", [])}
|
|
14
|
+
msg := sprintf(".vscode/extensions.json: recommendations має містити %q (rego.mdc)", [rec])
|
|
19
15
|
}
|
|
@@ -1,38 +1,30 @@
|
|
|
1
1
|
# Перевірка `.vscode/settings.json` для rego (rego.mdc).
|
|
2
2
|
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# "editor.formatOnSave": true } }
|
|
9
|
-
#
|
|
10
|
-
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
3
|
+
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
+
# Структура --data сформована з template/settings.json.snippet.json.
|
|
5
|
+
# Snippet — 2-рівнева мапа: <language-block-key>.<setting-key> = <expected>
|
|
6
|
+
# (VS Code-конвенція: ключі `[rego]` і `editor.defaultFormatter`/`editor.formatOnSave`
|
|
7
|
+
# — це літеральні string-keys із дужками/крапкою, не вкладені обʼєкти).
|
|
11
8
|
package rego.vscode_settings
|
|
12
9
|
|
|
13
10
|
import rego.v1
|
|
14
11
|
|
|
15
|
-
#
|
|
16
|
-
|
|
17
|
-
deny contains msg if {
|
|
18
|
-
not is_object(object.get(input, "[rego]", null))
|
|
19
|
-
msg := concat(" ", [
|
|
20
|
-
".vscode/settings.json: \"[rego]\" має бути обʼєктом з",
|
|
21
|
-
"\"editor.defaultFormatter\": \"tsandall.opa\" і",
|
|
22
|
-
"\"editor.formatOnSave\": true (rego.mdc)",
|
|
23
|
-
])
|
|
24
|
-
}
|
|
25
|
-
|
|
12
|
+
# Leaf-by-leaf: працює коли block присутній і є обʼєктом.
|
|
26
13
|
deny contains msg if {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
some block_key, expected_inner in data.template.snippet
|
|
15
|
+
inner := object.get(input, block_key, {})
|
|
16
|
+
is_object(inner)
|
|
17
|
+
some leaf_key, expected_value in expected_inner
|
|
18
|
+
actual := object.get(inner, leaf_key, null)
|
|
19
|
+
actual != expected_value
|
|
20
|
+
msg := sprintf(".vscode/settings.json: %s.%s має бути %v (rego.mdc)", [block_key, leaf_key, expected_value])
|
|
31
21
|
}
|
|
32
22
|
|
|
23
|
+
# Block існує, але не обʼєкт (напр. рядок) — окрема помилка типу.
|
|
33
24
|
deny contains msg if {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
some block_key in object.keys(data.template.snippet)
|
|
26
|
+
raw := object.get(input, block_key, null)
|
|
27
|
+
raw != null
|
|
28
|
+
not is_object(raw)
|
|
29
|
+
msg := sprintf(".vscode/settings.json: %s має бути обʼєктом (rego.mdc)", [block_key])
|
|
38
30
|
}
|
package/rules/rego/rego.mdc
CHANGED
|
@@ -15,19 +15,21 @@ alwaysApply: false
|
|
|
15
15
|
bun run lint-rego
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Цілі — `npm/policy
|
|
18
|
+
Цілі — `npm/rules/` (рекурсивно знаходить `.rego` у `<rule>/policy/<concern>/`). Інші *.rego поза деревом додай у `LINT_TARGETS` у `npm/rules/rego/lint/lint.mjs`.
|
|
19
19
|
|
|
20
20
|
`opa` і `regal` — лише у `PATH`, **не** додавай у `dependencies` / `devDependencies`.
|
|
21
21
|
|
|
22
22
|
### `package.json`
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
- Канон `scripts.lint-rego`: [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json)
|
|
25
|
+
|
|
26
|
+
### `.vscode/extensions.json`
|
|
27
|
+
|
|
28
|
+
- Канон `recommendations` має містити `tsandall.opa` (LSP, format-on-save через `opa fmt`): [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
|
|
29
|
+
|
|
30
|
+
### `.vscode/settings.json`
|
|
31
|
+
|
|
32
|
+
- Канон `[rego]`-block (`editor.defaultFormatter` + `editor.formatOnSave`): [settings.json.snippet.json](./policy/vscode_settings/template/settings.json.snippet.json)
|
|
31
33
|
|
|
32
34
|
## Конфіг regal
|
|
33
35
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# TODO:
|
|
2
|
+
|
|
3
|
+
## semgrep --config p/kubernetes
|
|
4
|
+
|
|
5
|
+
p/security-audit
|
|
6
|
+
|
|
7
|
+
p/secrets
|
|
8
|
+
|
|
9
|
+
p/nodejs
|
|
10
|
+
|
|
11
|
+
p/javascript
|
|
12
|
+
|
|
13
|
+
p/typescript
|
|
14
|
+
|
|
15
|
+
p/docker
|
|
16
|
+
|
|
17
|
+
p/kubernetes
|
|
18
|
+
|
|
19
|
+
## Trivy
|
|
20
|
+
Найцінніша частина Trivy
|
|
21
|
+
|
|
22
|
+
НЕ image scanning. А:
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
config scanning
|
|
26
|
+
+
|
|
27
|
+
Kubernetes scanning
|