@nitra/cursor 1.8.221 → 1.8.222
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/.claude-template/npm-CLAUDE.md +4 -0
- package/CHANGELOG.md +15 -0
- package/bin/auto-rules.md +2 -0
- package/mdc/tauri.mdc +20 -0
- package/package.json +1 -1
- package/policy/k8s/base_kustomization/base_kustomization.rego +40 -0
- package/policy/k8s/base_kustomization/base_kustomization_test.rego +36 -0
- package/policy/k8s/base_manifest/base_manifest.rego +154 -0
- package/policy/k8s/base_manifest/base_manifest_test.rego +94 -0
- package/policy/k8s/gateway/gateway.rego +151 -0
- package/policy/k8s/gateway/gateway_test.rego +122 -0
- package/policy/k8s/hasura_configmap/hasura_configmap.rego +69 -0
- package/policy/k8s/hasura_configmap/hasura_configmap_test.rego +49 -0
- package/policy/k8s/hasura_httproute/hasura_httproute.rego +298 -0
- package/policy/k8s/hasura_httproute/hasura_httproute_test.rego +148 -0
- package/policy/k8s/hpa_pdb/hpa_pdb.rego +139 -0
- package/policy/k8s/hpa_pdb/hpa_pdb_test.rego +101 -0
- package/policy/k8s/kustomization/kustomization.rego +220 -0
- package/policy/k8s/kustomization/kustomization_test.rego +128 -0
- package/policy/k8s/kustomize_managed/kustomize_managed.rego +31 -0
- package/policy/k8s/kustomize_managed/kustomize_managed_test.rego +30 -0
- package/policy/k8s/manifest/manifest.rego +151 -4
- package/policy/k8s/manifest/manifest_test.rego +309 -0
- package/policy/k8s/svc_hl_yaml/svc_hl_yaml.rego +51 -0
- package/policy/k8s/svc_hl_yaml/svc_hl_yaml_test.rego +42 -0
- package/policy/k8s/svc_yaml/svc_yaml.rego +31 -0
- package/policy/k8s/svc_yaml/svc_yaml_test.rego +41 -0
- package/scripts/lint-conftest.mjs +73 -1
- package/scripts/lint-rego.mjs +19 -4
|
@@ -79,6 +79,16 @@ const K8S_DIR_PATH_RE = /(^|\/)k8s\//u
|
|
|
79
79
|
const K8S_HC_YAML_PATH_RE = /(^|\/)k8s\/.+\/hc\.yaml$/u
|
|
80
80
|
/** `…/k8s/…/base/…/hr.yaml` (HTTPRoute у base-шарі). */
|
|
81
81
|
const K8S_BASE_HR_YAML_PATH_RE = /(^|\/)k8s\/.*base\/.*hr\.yaml$/u
|
|
82
|
+
/** `kustomization.yaml` будь-де під сегментом `k8s/`. */
|
|
83
|
+
const K8S_KUSTOMIZATION_PATH_RE = /(^|\/)k8s\/.*\/kustomization\.yaml$/u
|
|
84
|
+
/** `…/k8s/.../base/.../kustomization.yaml`. */
|
|
85
|
+
const K8S_BASE_KUSTOMIZATION_PATH_RE = /(^|\/)k8s\/.*base\/(?:.*\/)?kustomization\.yaml$/u
|
|
86
|
+
/** Будь-який ресурсний `*.yaml` під сегментом `…/k8s/.../base/...`, окрім `kustomization.yaml`. */
|
|
87
|
+
const K8S_BASE_MANIFEST_PATH_RE = /(^|\/)k8s\/.*base\//u
|
|
88
|
+
/** `…/k8s/.../svc.yaml` (cluster-IP Service). */
|
|
89
|
+
const K8S_SVC_YAML_PATH_RE = /(^|\/)k8s\/.+\/svc\.yaml$/u
|
|
90
|
+
/** `…/k8s/.../svc-hl.yaml` (headless Service). */
|
|
91
|
+
const K8S_SVC_HL_YAML_PATH_RE = /(^|\/)k8s\/.+\/svc-hl\.yaml$/u
|
|
82
92
|
|
|
83
93
|
/** @type {ConftestTarget[]} */
|
|
84
94
|
const TARGETS = [
|
|
@@ -221,11 +231,73 @@ const TARGETS = [
|
|
|
221
231
|
// Усі YAML у дереві з сегментом `k8s` — пер-документні структурні правила.
|
|
222
232
|
{
|
|
223
233
|
namespace: 'k8s.manifest',
|
|
224
|
-
policyDir: 'k8s',
|
|
234
|
+
policyDir: 'k8s/manifest',
|
|
225
235
|
rule: 'k8s',
|
|
226
236
|
walk: { match: rel => K8S_DIR_PATH_RE.test(rel) && (rel.endsWith('.yaml') || rel.endsWith('.yml')) }
|
|
227
237
|
},
|
|
228
238
|
|
|
239
|
+
// Gateway API + HealthCheckPolicy — застосовується до будь-якого YAML під k8s
|
|
240
|
+
// (правила перевіряють лише відповідні kind / apiVersion).
|
|
241
|
+
{
|
|
242
|
+
namespace: 'k8s.gateway',
|
|
243
|
+
policyDir: 'k8s/gateway',
|
|
244
|
+
rule: 'k8s',
|
|
245
|
+
walk: { match: rel => K8S_DIR_PATH_RE.test(rel) && (rel.endsWith('.yaml') || rel.endsWith('.yml')) }
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
// Структурні перевірки HPA / PDB (apiVersion / behavior / metrics / selector).
|
|
249
|
+
{
|
|
250
|
+
namespace: 'k8s.hpa_pdb',
|
|
251
|
+
policyDir: 'k8s/hpa_pdb',
|
|
252
|
+
rule: 'k8s',
|
|
253
|
+
walk: { match: rel => K8S_DIR_PATH_RE.test(rel) && (rel.endsWith('.yaml') || rel.endsWith('.yml')) }
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
// Kustomization-файли: resources sort, patches sort, JSON6902 conflicts.
|
|
257
|
+
{
|
|
258
|
+
namespace: 'k8s.kustomization',
|
|
259
|
+
policyDir: 'k8s/kustomization',
|
|
260
|
+
rule: 'k8s',
|
|
261
|
+
walk: { match: rel => K8S_KUSTOMIZATION_PATH_RE.test(rel) }
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
// svc.yaml — cluster-IP Service.
|
|
265
|
+
{
|
|
266
|
+
namespace: 'k8s.svc_yaml',
|
|
267
|
+
policyDir: 'k8s/svc_yaml',
|
|
268
|
+
rule: 'k8s',
|
|
269
|
+
walk: { match: rel => K8S_SVC_YAML_PATH_RE.test(rel) }
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
// svc-hl.yaml — headless Service з суфіксом `-hl`.
|
|
273
|
+
{
|
|
274
|
+
namespace: 'k8s.svc_hl_yaml',
|
|
275
|
+
policyDir: 'k8s/svc_hl_yaml',
|
|
276
|
+
rule: 'k8s',
|
|
277
|
+
walk: { match: rel => K8S_SVC_HL_YAML_PATH_RE.test(rel) }
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
// base/kustomization.yaml — обов'язкове непорожнє поле `namespace:`.
|
|
281
|
+
{
|
|
282
|
+
namespace: 'k8s.base_kustomization',
|
|
283
|
+
policyDir: 'k8s/base_kustomization',
|
|
284
|
+
rule: 'k8s',
|
|
285
|
+
walk: { match: rel => K8S_BASE_KUSTOMIZATION_PATH_RE.test(rel) }
|
|
286
|
+
},
|
|
287
|
+
|
|
288
|
+
// Ресурсні маніфести під `…/k8s/.../base/...` (окрім kustomization.yaml).
|
|
289
|
+
{
|
|
290
|
+
namespace: 'k8s.base_manifest',
|
|
291
|
+
policyDir: 'k8s/base_manifest',
|
|
292
|
+
rule: 'k8s',
|
|
293
|
+
walk: {
|
|
294
|
+
match: rel =>
|
|
295
|
+
K8S_BASE_MANIFEST_PATH_RE.test(rel) &&
|
|
296
|
+
!K8S_BASE_KUSTOMIZATION_PATH_RE.test(rel) &&
|
|
297
|
+
(rel.endsWith('.yaml') || rel.endsWith('.yml'))
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
|
|
229
301
|
// abie HealthCheckPolicy: `hc.yaml` у дереві k8s.
|
|
230
302
|
{
|
|
231
303
|
namespace: 'abie.health_check_policy',
|
package/scripts/lint-rego.mjs
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Лінт Rego-полісі (`conftest.mdc` + `rego.mdc`): preflight на `opa` і `regal`,
|
|
3
|
-
* далі послідовно `opa check --strict
|
|
3
|
+
* далі послідовно `opa check --strict`, `regal lint` і опційний
|
|
4
|
+
* `conftest verify` (для `*_test.rego`-файлів) якщо conftest у PATH.
|
|
4
5
|
*
|
|
5
|
-
* Чому
|
|
6
|
+
* Чому два-три інструменти:
|
|
6
7
|
* - `opa check --strict` — компіляція з типами і строгим режимом (мертвий код, неоднозначні
|
|
7
8
|
* правила, незадекларовані змінні). Ловить помилки, які `regal` навмисно лишає поза скоупом
|
|
8
9
|
* (він — про стиль і ідіоматичність, а не про компіляцію).
|
|
9
10
|
* - `regal lint` (https://docs.styra.com/regal) — статичний лінтер Rego: ловить v0-синтаксис,
|
|
10
11
|
* неявні set-rules та інші відхилення від `rego.v1`, плюс bugs/idiomatic/performance-правила.
|
|
12
|
+
* - `conftest verify` (опційно) — виконує `test_*` правила у `*_test.rego` (юніт-тести політик).
|
|
13
|
+
* Якщо conftest відсутній у PATH — пропускаємо без помилки (тести опційні в локальному середовищі;
|
|
14
|
+
* у CI потрібно встановити conftest).
|
|
11
15
|
*
|
|
12
16
|
* Без preflight-у на бінарники лінт мовчки злетить з невиразним повідомленням від shell —
|
|
13
17
|
* друкуємо явні install-hints (як це робить `lint-ga.mjs` для shellcheck/uv). `opa` додатково
|
|
@@ -16,7 +20,7 @@
|
|
|
16
20
|
*
|
|
17
21
|
* Цілі лінту: `npm/policy/` (місце, де поки що живуть Rego-полісі пакета `@nitra/cursor`).
|
|
18
22
|
* Якщо в репозиторії з’являться інші *.rego поза цим деревом, додай шлях у `LINT_TARGETS` —
|
|
19
|
-
*
|
|
23
|
+
* усі три інструменти приймають кілька шляхів і самі рекурсивно обходять директорії.
|
|
20
24
|
*/
|
|
21
25
|
import { spawnSync } from 'node:child_process'
|
|
22
26
|
import { existsSync } from 'node:fs'
|
|
@@ -110,7 +114,18 @@ export function runLintRego(cwd = process.cwd()) {
|
|
|
110
114
|
const opaCode = runStep(opa, ['check', '--strict', ...targets], root)
|
|
111
115
|
if (opaCode !== 0) return opaCode
|
|
112
116
|
|
|
113
|
-
|
|
117
|
+
const regalCode = runStep(regal, ['lint', ...targets], root)
|
|
118
|
+
if (regalCode !== 0) return regalCode
|
|
119
|
+
|
|
120
|
+
const conftest = resolveCmd('conftest')
|
|
121
|
+
if (!conftest) {
|
|
122
|
+
console.log(
|
|
123
|
+
'ℹ conftest не знайдено в PATH — пропускаю `conftest verify` (юніт-тести *_test.rego).\n' +
|
|
124
|
+
' Встанови, щоб запустити локально: brew install conftest (macOS) або https://www.conftest.dev/install/'
|
|
125
|
+
)
|
|
126
|
+
return 0
|
|
127
|
+
}
|
|
128
|
+
return runStep(conftest, ['verify', ...targets.flatMap(t => ['-p', t])], root)
|
|
114
129
|
}
|
|
115
130
|
|
|
116
131
|
process.exitCode = runLintRego()
|