@nitra/cursor 1.8.63 → 1.8.64

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/mdc/k8s.mdc CHANGED
@@ -42,7 +42,7 @@ alwaysApply: false
42
42
  }
43
43
  ```
44
44
 
45
- Якщо правило **`k8s`** підключено в **`.n-cursor.json`** (масив **`rules`**), у **кореневому** `package.json` **обов'язково** мають бути скрипт **`lint-k8s`** і виклик **`bun run lint-k8s`** у агрегованому **`lint`** (див. **`bun.mdc`**). Це перевіряє **`npx @nitra/cursor check bun`**.
45
+ Якщо правило **`k8s`** підключено в **`.n-cursor.json`** (масив **`rules`**), у **кореневому** `package.json` **мають** бути скрипт **`lint-k8s`** і виклик **`bun run lint-k8s`** у агрегованому **`lint`** (див. **`bun.mdc`**). Це перевіряє **`npx @nitra/cursor check bun`**.
46
46
 
47
47
  Шлях до скрипта підстав свій (`./scripts/…` після копіювання, `node_modules/@nitra/cursor/scripts/…` якщо пакет у залежностях).
48
48
 
@@ -96,34 +96,25 @@ jobs:
96
96
 
97
97
  ## Deployment: `resources`
98
98
 
99
- Для **`kind: Deployment`** у кожному контейнері **`spec.template.spec.containers[]`** має бути явне поле **`resources`**. Якщо ліміти та requests ще не задані, додай порожній об'єкт:
99
+ У **`Deployment`** у кожному **`containers`** / **`initContainers`** має бути **`resources`**; якщо лімітів ще немає мінімум порожній запис:
100
100
 
101
101
  ```yaml
102
102
  resources: {}
103
103
  ```
104
104
 
105
- Так маніфест явно резервує місце під **`requests` / `limits`** і уникає випадкового пропуску секції. **`check k8s`** перевіряє це для кожного YAML-документа **`Deployment`** у файлах під **`k8s`**.
105
+ **`check k8s`** перевіряє наявність **`resources`** у кожному документі **Deployment** під **`k8s`**. Поле **`imagePullPolicy`** скрипт **не** перевіряє (залишається політиці Kubernetes за тегом образу).
106
106
 
107
- **`imagePullPolicy`:** у маніфестах не вимагається; Kubernetes за замовчуванням: образ **без тега** або з **`:latest`** **Always**, з іншим тегом **IfNotPresent**. **`check k8s`** це поле не перевіряє.
108
-
109
- Якщо в **`Deployment`** у **`spec.template.spec.containers`** або **`initContainers`** задано образ **`hasura/graphql-engine`**, у полі **`image`** має бути саме **`hasura/graphql-engine:v2.48.15.ubi.amd64`** (для еквівалента Docker Hub допускається префікс **`docker.io/`**). Інші теги або сторонні реєстри з тим самим репозиторієм **`hasura/graphql-engine`** — порушення **`check k8s`**.
107
+ Образ **`hasura/graphql-engine`**: дозволений лише канонічний тег із константи **`HASURA_GRAPHQL_ENGINE_IMAGE`** у **`check-k8s.mjs`** (допускається префікс **`docker.io/`**); решта помилка **check k8s**.
110
108
 
111
109
  ## Service: заборонені анотації GKE
112
110
 
113
- У **`kind: Service`** не використовуй у **`metadata.annotations`** ключі:
114
-
115
- - **`cloud.google.com/neg`**
116
- - **`cloud.google.com/backend-config`**
117
-
118
- Вони потрібні для інтеграції з **Ingress** / класичним балансуванням GKE; після переходу на **Gateway API** їх слід **прибрати** з маніфестів. **`check k8s`** завершиться помилкою, якщо хоча б один із цих ключів присутній.
111
+ У **`kind: Service`** не додавай у **`metadata.annotations`** **`cloud.google.com/neg`** і **`cloud.google.com/backend-config`** (legacy під Ingress / старе балансування GKE). **check k8s** падає, якщо ключ є.
119
112
 
120
113
  ## Service: `svc.yaml` і `svc-hl.yaml` (Gateway API)
121
114
 
122
- - У тому самому каталозі, де лежить **`svc.yaml`**, обов’язково має бути **`svc-hl.yaml`**. Якщо файлу ще немає створи його як копію **`svc.yaml`**: для кожного **Service** задай **`metadata.name`** з суфіксом **`-hl`**, **`spec.clusterIP: None`** (headless), збережи селектор і порти як у кластерного сервісу; **`check k8s`** не генерує файли автоматично.
123
- - У **`svc.yaml`** кожен **Service** має мати **`spec.type: ClusterIP`**.
124
- - У **`svc-hl.yaml`** кожен **Service** має мати **`spec.clusterIP: None`** та **`metadata.name`**, що закінчується на **`-hl`**, узгоджено з відповідним ім’ям у **`svc.yaml`** (наприклад **`app`** **`app-hl`**).
125
- - У маршрутах **Gateway API** з групи **`gateway.networking.k8s.io`** (**`HTTPRoute`**, **`GRPCRoute`**, **`TCPRoute`**, **`TLSRoute`**, **`UDPRoute`**) посилання **`backendRefs`** / **`backendRef`** на **Service** мають вказувати лише сервіси з цього headless-файлу (ім’я з суфіксом **`-hl`**).
126
- - Якщо **`svc.yaml`** підключено через **`kustomization.yaml`** (**`resources`**, **`bases`**, **`components`**, **`crds`**, **`patches[].path`**, **`patchesStrategicMerge`**), у **тому ж** **`kustomization.yaml`** додай посилання на відповідний **`svc-hl.yaml`** (той самий відносний префікс каталогу, що й для **`svc.yaml`**).
115
+ Пара файлів для кластерного й headless **Service**: **`svc.yaml`** + **`svc-hl.yaml`** в одному каталозі, **`spec.type: ClusterIP`** / **`clusterIP: None`**, імена **`-hl`**, узгодженість пар, маршрути **`gateway.networking.k8s.io`** (**HTTPRoute**, **GRPCRoute**, **TCPRoute**, **TLSRoute**, **UDPRoute**) **backendRef** лише на сервіси з суфіксом **`-hl`**; якщо **kustomization** посилається на **`svc.yaml`**, у **тому ж** **`kustomization.yaml`** має бути посилання на sibling **`svc-hl.yaml`**. Скрипт **не** створює файли — додай **`svc-hl.yaml`** вручну (копія з правками **name** / **clusterIP**).
116
+
117
+ **Точні умови та повідомлення `fail`** верхній JSDoc **`npm/scripts/check-k8s.mjs`**.
127
118
 
128
119
  ## Kustomize: структура каталогів (`base` / overlays)
129
120
 
@@ -142,11 +133,11 @@ resources: {}
142
133
 
143
134
  ### Namespace
144
135
 
145
- - **`base/kustomization.yaml`:** у цьому файлі поле **`namespace:`** **завжди** має бути присутнє й **непорожнє**, щоб Kustomize застосував один цільовий namespace до ресурсів **base**. **`check k8s`** перевіряє це, коли файл є в репозиторії.
136
+ - **`base/kustomization.yaml`:** поле **`namespace:`** має бути **непорожнім** (перевіряє **check k8s**, якщо файл є).
146
137
 
147
- - **Де не дублювати `metadata.namespace`:** у YAML під **`k8s`**, чиї шляхи **досяжні** з будь-якого **`kustomization.yaml`** через **`resources`**, **`bases`**, **`components`**, **`crds`**, елементи **`patches`** з полем **`path`**, **`patchesStrategicMerge`** (транзитивно, зокрема через каталог із дочірнім **`kustomization.yaml`**). У таких файлах **не** вказуй **`metadata.namespace`** — його виставляє Kustomize за полем **`namespace:`** у kustomization.
138
+ - **Де не дублювати `metadata.namespace`:** у YAML, досяжних через **граф Kustomize** (шляхи з **`kustomization.yaml`**, як у логіці **`collectKustomizeManagedRelPaths`** / **check k8s**). **Namespace** задає **`namespace:`** у kustomization.
148
139
 
149
- - **Коли `metadata.namespace` обов’язковий:** YAML під **`k8s`**, який **ніде** не перелічений у згаданих полях жодного kustomization-файлу, має містити **непорожній** **`metadata.namespace`** у кожному документі з **`apiVersion`** та **`kind`**, **окрім** кластерних ресурсів (наприклад **`Namespace`**, **`ClusterRole`**, **`PersistentVolume`** — повний перелік у **`check-k8s.mjs`**, **`CLUSTER_SCOPED_KINDS`**). Якщо файл має бути без namespace у маніфесті — підключи його до kustomization через **`resources`** / **`patches`** тощо.
140
+ - **Коли `metadata.namespace` обов’язковий у файлі:** YAML під **`k8s`**, який **не** в графі жодного kustomization непорожній **`metadata.namespace`** для namespaced **kind** (винятки кластерні **kind**, перелік **`CLUSTER_SCOPED_KINDS`** у **`check-k8s.mjs`**). Якщо namespace у маніфесті не потрібен — підключи файл через **`resources`** / **`patches`** тощо.
150
141
 
151
142
  - **Не додавай** окремі **patches** Kustomize, які лише змінюють **namespace**: **namespace** визначає Kustomize; у overlays додаткові зміни — без дублювання логіки **namespace**.
152
143
 
@@ -182,27 +173,56 @@ resources: {}
182
173
 
183
174
  **`check k8s`:** заборонено **`kind: Ingress`**.
184
175
 
185
- ## Перевірка
176
+ 3. Якщо **HTTPRoute** посилається на **Service** в іншому **namespace**, потрібен **ReferenceGrant** (дозвіл). Наприклад **HTTPRoute** в **`contract`** і **Service** в **`dev`** — додай маніфест на кшталт **`base/rg.yaml`** (фрагмент нижче).
177
+
178
+ ```yaml title="base/rg.yaml"
179
+ # yaml-language-server: $schema=https://datreeio.github.io/CRDs-catalog/gateway.networking.k8s.io/referencegrant_v1beta1.json
180
+ apiVersion: gateway.networking.k8s.io/v1beta1
181
+ kind: ReferenceGrant
182
+ metadata:
183
+ name: contract-to-dev
184
+ namespace: dev
185
+ spec:
186
+ from:
187
+ - group: gateway.networking.k8s.io
188
+ kind: HTTPRoute
189
+ namespace: contract
190
+ to:
191
+ - group: ''
192
+ kind: Service
193
+ # Якщо name не вказано, доступ дозволено до всіх Service в цьому namespace
194
+ ```
195
+
196
+ **ReferenceGrant** має бути в **namespace** тих **Service**, до яких відкривається доступ (у прикладі — **`dev`**). Якщо **`namespace:`** у **overlay** не збігається з **namespace** гранта, **не** додавай **`base/rg.yaml`** у **`resources:`** того overlay — Kustomize може перезаписати **`metadata.namespace`** гранта. Натомість застосуй **`patches`** (JSON patch), щоб явно виставити потрібний **namespace**:
197
+
198
+ ```yaml title="overlay/kustomization.yaml (фрагмент)"
199
+ patches:
200
+ - target:
201
+ kind: ReferenceGrant
202
+ name: contract-to-dev
203
+ patch: |-
204
+ - op: replace
205
+ path: /metadata/namespace
206
+ value: dev
207
+ ```
186
208
 
187
- **`npx @nitra/cursor check k8s`** — деталі умов у **JSDoc на початку** **`npm/scripts/check-k8s.mjs`**; канон URL **`$schema`** для редактору — розділ **«Визначення схеми YAML»** нижче. Якщо під `k8s` немає `*.yaml` — перевірку пропущено. Решту політик кластера / compliance закриває **`lint-k8s`**.
209
+ ## Перевірка
188
210
 
189
- Після змін у маніфестах: **`bun run lint-k8s`** (kubeconform + kubescape).
211
+ **`npx @nitra/cursor check k8s`** програмні критерії в **JSDoc на початку** **`npm/scripts/check-k8s.mjs`**. Якщо під **`k8s`** немає **`*.yaml`** — крок пропущено. Канон **`$schema`** для редактора — розділ **«Визначення схеми YAML`** нижче.
190
212
 
191
- ## Що закодовано в `check-k8s.mjs`
213
+ **Не входить у check k8s:** наприклад **ReferenceGrant** і доступ між **namespace** (лише рекомендації тут), **kubeconform** / **kubescape** — це **`bun run lint-k8s`**.
192
214
 
193
- Не дублюй тут повний перелік — він у **верхньому JSDoc** **`npm/scripts/check-k8s.mjs`** і в константах (**`YANNH_PIN`**, **`YANNH_GROUPS`**, **`EXPLICIT_K8S_SCHEMAS`**, **`CLUSTER_SCOPED_KINDS`**, **`HASURA_GRAPHQL_ENGINE_IMAGE`** тощо).
215
+ ## Що саме в скрипті `check-k8s.mjs`
194
216
 
195
- Коротко: **`$schema`** (один modeline, без **`.yml`** під **`k8s`**), заборона **Ingress**, **Deployment.resources**, пін **hasura/graphql-engine**, **Service** без анотацій NEG/backend-config, пари **`svc.yaml`** / **`svc-hl.yaml`** (**ClusterIP** / headless **`-hl`**) і їхні записи в **`kustomization.yaml`**, **Gateway API** маршрути **backendRef** лише на **`-hl`**, **`metadata.namespace`** залежно від **base** і графа Kustomize, заборона **`…/k8s/dev/…`**, непорожній **`namespace:`** у **`k8s/base/kustomization.yaml`**, видалення файлів, де всі документи — лише **BackendConfig** (змішані файли — помилка).
217
+ Повний перелік умов, константи (**`YANNH_PIN`**, **`CLUSTER_SCOPED_KINDS`**, **`HASURA_GRAPHQL_ENGINE_IMAGE`** тощо) і допоміжні функції у файлі скрипта; змінив вимогу для **check** онови **JSDoc** і за потреби тести в **`npm/tests/check-k8s-schema.test.mjs`**.
196
218
 
197
- При зміні **PIN** версії Kubernetes оновлюй узгоджено **`check-k8s.mjs`**, **`run-k8s.mjs`** (**`KUBERNETES_VERSION`**, **`DATREE_CRD_SCHEMA_LOCATION`**) і розділи **lint-k8s** / **Визначення схеми YAML** у цьому файлі (**`YANNH_REF`**, **`YANNH_GROUPS`**, **`DATREE_CRD_BASE`** — за потреби в скрипті).
219
+ При зміні **PIN** версії Kubernetes узгодь **`check-k8s.mjs`**, **`run-k8s.mjs`** (**`KUBERNETES_VERSION`**, **`DATREE_CRD_SCHEMA_LOCATION`**) і цей файл (**lint-k8s**, **Визначення схеми YAML**).
198
220
 
199
221
  ## Коли застосовувати (агентам)
200
222
 
201
- - Зміни в k8s YAML після правок **`check k8s`**.
202
- - Якщо перший рядок уже коректний і URL відповідає `apiVersion` / `kind`не дублюй; змінився ресурс онови лише `$schema`.
203
- - У **`Deployment`** без поля **`resources`** у контейнері додай **`resources: {}`** (див. розділ **Deployment: `resources`**). **`imagePullPolicy`** за потреби не дублюй — достатньо політики Kubernetes за тегом образу.
204
- - Дотримуйся структури **Kustomize** (`base` = dev, overlays без дублювання `base`, коментарі для рядків, що змінюються в overlay). У **`base/kustomization.yaml`** завжди задавай непорожній **`namespace:`**. У **`k8s/base`** у кожному ресурсному YAML має бути явний **`metadata.namespace`**. Поза **base**, якщо не хочеш **`metadata.namespace`** у файлі — підключи його до kustomization (**`resources`** / **`patches`** тощо); інакше додай явний **`metadata.namespace`**.
205
- - Після міграції на нову структуру **видали** застарілі файли та каталоги, які вже замінені (див. **Міграція зі старої структури**).
223
+ - Після змін у k8s YAML: **`npx @nitra/cursor check k8s`** і за наявності правила — **`bun run lint-k8s`**.
224
+ - Оновив **`apiVersion` / `kind`**підправ **перший** рядок **`$schema`** (див. **Визначення схеми YAML**).
225
+ - Дотримуйся **Kustomize** з цього правила; деталі **namespace** / графа ресурсів **check k8s** + підказки в JSDoc скрипта.
206
226
 
207
227
  ## Визначення схеми YAML (канон)
208
228
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "1.8.63",
3
+ "version": "1.8.64",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
@@ -6,9 +6,9 @@
6
6
  * (datree за замовчуванням: GitHub Pages `https://datreeio.github.io/CRDs-catalog/…`).
7
7
  *
8
8
  * Додатково: у кожному YAML-документі з **`kind: Deployment`** у кожного контейнера
9
- * **`spec.template.spec.containers[]`** має бути ключ **`resources`** (значення — об'єкт, допускається
9
+ * **`spec.template.spec.containers[]`** має бути ключ **`resources`** (значення — об’єкт, допускається
10
10
  * порожній **`{}`**). Поле **`imagePullPolicy`** не перевіряється — діють типові правила Kubernetes
11
- * (`:latest` або без тега → **Always**, інші теги → **IfNotPresent**). Якщо серед **`containers`** /
11
+ * (`:latest` або коли тег не вказано → **Always**, інші теги → **IfNotPresent**). Якщо серед **`containers`** /
12
12
  * **`initContainers`** є образ **`hasura/graphql-engine`**, дозволено лише пін **`HASURA_GRAPHQL_ENGINE_IMAGE`**
13
13
  * (див. k8s.mdc).
14
14
  *
@@ -327,7 +327,7 @@ export function kustomizationSvcYamlMissingSvcHlViolation(kustomizationDir, path
327
327
  if (basename(abs).toLowerCase() === 'svc.yaml') {
328
328
  const hlAbs = resolve(dirname(abs), 'svc-hl.yaml')
329
329
  if (!resolved.has(hlAbs)) {
330
- return `kustomization посилається на «${ref}» — додай у тому ж kustomization.yaml посилання на відповідний svc-hl.yaml (очікуваний шлях поруч, напр. той самий префікс каталогу + svc-hl.yaml; див. k8s.mdc)`
330
+ return `kustomization посилається на «${ref}» — додай у тому ж kustomization.yaml посилання на відповідний svc-hl.yaml (очікуваний шлях поруч, наприклад той самий префікс каталогу + svc-hl.yaml; див. k8s.mdc)`
331
331
  }
332
332
  }
333
333
  }
@@ -627,9 +627,9 @@ async function readK8sYamlBodyAfterModelineForSvcPair(abs) {
627
627
  }
628
628
 
629
629
  /**
630
- * Розбирає YAML на корені документів-об’єктів (ігнорує зламані документи).
630
+ * Розбирає YAML на корені документів (ігнорує зламані документи).
631
631
  * @param {string} body фрагмент YAML
632
- * @returns {unknown[]} масив об’єктів-документів
632
+ * @returns {unknown[]} масив успішно розібраних коренів YAML-документів
633
633
  */
634
634
  function parseK8sYamlDocumentObjectRoots(body) {
635
635
  try {
@@ -722,7 +722,7 @@ function scanIngressInYamlDocuments(rel, body, fail) {
722
722
 
723
723
  /**
724
724
  * Чи порушує маніфест вимогу **`Deployment.spec.template.spec.containers[].resources`** (див. k8s.mdc).
725
- * @param {unknown} manifest корінь YAML-документа як об'єкт JavaScript
725
+ * @param {unknown} manifest корінь YAML-документа як запис JavaScript
726
726
  * @returns {string | null} текст порушення для `fail` або null, якщо перевірка не застосовується / ок
727
727
  */
728
728
  export function deploymentResourcesViolation(manifest) {
@@ -752,7 +752,7 @@ export function deploymentResourcesViolation(manifest) {
752
752
  }
753
753
  const r = cont.resources
754
754
  if (r === null || typeof r !== 'object' || Array.isArray(r)) {
755
- return `контейнер "${label}": resources має бути об'єктом (наприклад порожній об'єкт у YAML: resources: {})`
755
+ return `контейнер "${label}": resources має бути записом у YAML (наприклад порожній: resources: {})`
756
756
  }
757
757
  }
758
758
  }
@@ -761,7 +761,7 @@ export function deploymentResourcesViolation(manifest) {
761
761
  }
762
762
 
763
763
  /**
764
- * Прибирає digest з посилання на образ (`@sha256:…`) для порівняння тега.
764
+ * Прибирає digest з посилання на образ (`@sha256:…`) для порівняння тегу образу.
765
765
  * @param {string} image значення поля `image`
766
766
  * @returns {string} той самий рядок без суфікса `@…` (digest), з `.trim()`
767
767
  */
@@ -771,7 +771,7 @@ function stripImageDigest(image) {
771
771
  }
772
772
 
773
773
  /**
774
- * Чи рядок `image` вказує на репозиторій **hasura/graphql-engine** (будь-який тег / без тега).
774
+ * Чи рядок `image` вказує на репозиторій **hasura/graphql-engine** (будь-який тег / без вказаного тегу).
775
775
  * @param {string} image значення поля `image`
776
776
  * @returns {boolean} true, якщо шлях образу закінчується на `hasura/graphql-engine` з тегом або без
777
777
  */
@@ -808,7 +808,7 @@ function hasuraGraphqlEngineViolationInContainerList(list, containers) {
808
808
  }
809
809
 
810
810
  /**
811
- * Чи порушує **Deployment** вимогу пінованого образу **hasura/graphql-engine** (k8s.mdc).
811
+ * Чи порушує **Deployment** вимогу щодо зафіксованого образу **hasura/graphql-engine** (k8s.mdc).
812
812
  * @param {unknown} manifest корінь YAML-документа
813
813
  * @returns {string | null} текст порушення або null, якщо не Deployment / образу немає / ок
814
814
  */