@nitra/cursor 12.8.6 → 12.8.8
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 +12 -0
- package/package.json +1 -1
- package/rules/abie/main.mdc +9 -5
- package/rules/abie/policy/base_deployment_preem/base_deployment_preem.mdc +22 -0
- package/rules/abie/policy/clean_merged_ignore_branches/clean_merged_ignore_branches.mdc +19 -0
- package/rules/abie/policy/health_check_policy/health_check_policy.mdc +17 -0
- package/rules/abie/policy/http_route_base/http_route_base.mdc +9 -0
- package/rules/abie/policy/package_json_shared/package_json_shared.mdc +17 -0
- package/rules/adr/js/hooks.mdc +32 -0
- package/rules/adr/js/madr_format.mdc +96 -0
- package/rules/adr/js/settings_policy.mdc +34 -0
- package/rules/adr/main.mdc +17 -95
- package/rules/adr/policy/settings_json/settings_json.mdc +7 -0
- package/rules/adr/policy/settings_local_json/settings_local_json.mdc +7 -0
- package/rules/bun/js/bunfig.mdc +12 -0
- package/rules/bun/js/layout.mdc +60 -0
- package/rules/bun/js/lint.mdc +9 -0
- package/rules/bun/js/package_json.mdc +19 -0
- package/rules/bun/main.mdc +7 -60
- package/rules/bun/policy/bunfig/bunfig.mdc +12 -0
- package/rules/bun/policy/package_json/package_json.mdc +14 -0
- package/rules/capacitor/js/ios_spm.mdc +69 -0
- package/rules/capacitor/js/version.mdc +29 -0
- package/rules/capacitor/main.mdc +6 -22
- package/rules/capacitor/policy/package_json/package_json.mdc +9 -0
- package/rules/changelog/js/agent-workflow.mdc +15 -0
- package/rules/changelog/js/changelog-format.mdc +33 -0
- package/rules/changelog/js/comparison-models.mdc +40 -0
- package/rules/changelog/main.mdc +4 -98
- package/rules/ci4/js/marksman_config.mdc +31 -0
- package/rules/ci4/js/vscode_extensions.mdc +33 -0
- package/rules/ci4/main.mdc +16 -14
- package/rules/ci4/policy/vscode_extensions/vscode_extensions.mdc +9 -0
- package/rules/docker/js/compile.mdc +44 -0
- package/rules/docker/js/hadolint.mdc +50 -0
- package/rules/docker/js/mirror.mdc +13 -0
- package/rules/docker/js/multistage.mdc +13 -0
- package/rules/docker/js/native-addon.mdc +43 -0
- package/rules/docker/js/nginx-tag.mdc +7 -0
- package/rules/docker/js/nginx-user.mdc +37 -0
- package/rules/docker/js/non-root.mdc +39 -0
- package/rules/docker/main.mdc +13 -196
- package/rules/docker/policy/lint_docker_yml/lint_docker_yml.mdc +14 -0
- package/rules/efes/main.mdc +1 -1
- package/rules/efes/policy/package_json_shared/package_json_shared.mdc +30 -0
- package/rules/ga/js/lint_toolchain.mdc +15 -0
- package/rules/ga/js/required_workflows.mdc +35 -0
- package/rules/ga/js/vscode.mdc +17 -0
- package/rules/ga/js/workflow_common.mdc +108 -0
- package/rules/ga/js/workflows.mdc +32 -0
- package/rules/ga/js/zizmor.mdc +7 -0
- package/rules/ga/main.mdc +16 -119
- package/rules/ga/policy/clean_ga_workflows/clean_ga_workflows.mdc +18 -0
- package/rules/ga/policy/clean_merged_branch/clean_merged_branch.mdc +22 -0
- package/rules/ga/policy/git_ai/git_ai.mdc +19 -0
- package/rules/ga/policy/lint_ga/lint_ga.mdc +21 -0
- package/rules/ga/policy/vscode_extensions/vscode_extensions.mdc +9 -0
- package/rules/ga/policy/vscode_settings/vscode_settings.mdc +9 -0
- package/rules/ga/policy/workflow_common/workflow_common.mdc +18 -0
- package/rules/ga/policy/zizmor_yml/zizmor_yml.mdc +9 -0
- package/rules/graphql/js/tooling.mdc +13 -0
- package/rules/graphql/js/vscode_extensions.mdc +13 -0
- package/rules/graphql/main.mdc +4 -21
- package/rules/graphql/policy/vscode_extensions/vscode_extensions.mdc +9 -0
- package/rules/hasura/js/internal_urls.mdc +27 -0
- package/rules/hasura/js/migrations.mdc +13 -0
- package/rules/hasura/js/svc_hl.mdc +17 -0
- package/rules/hasura/main.mdc +6 -30
- package/rules/hasura/policy/svc_hl/svc_hl.mdc +15 -0
- package/rules/image-avif/js/avif_generation.mdc +26 -0
- package/rules/image-avif/js/package_json_optout.mdc +21 -0
- package/rules/image-avif/main.mdc +5 -34
- package/rules/image-avif/policy/package_json/package_json.mdc +18 -0
- package/rules/image-compress/js/package_json.mdc +7 -0
- package/rules/image-compress/js/package_setup.mdc +13 -0
- package/rules/image-compress/main.mdc +4 -12
- package/rules/image-compress/policy/package_json/package_json.mdc +13 -0
- package/rules/js/docs/index.md +3 -3
- package/rules/js/js/dep-policy.mdc +17 -0
- package/rules/js/js/eslint-config.mdc +28 -0
- package/rules/js/js/extensions.mdc +8 -0
- package/rules/js/js/file-extensions.mdc +12 -0
- package/rules/js/js/for-in.mdc +26 -0
- package/rules/js/js/jscpd.mdc +42 -0
- package/rules/js/js/knip.mdc +15 -0
- package/rules/js/js/lint-js-workflow.mdc +58 -0
- package/rules/js/js/oxlintrc.mdc +20 -0
- package/rules/js/js/package-json.mdc +31 -0
- package/rules/js/js/tests.mdc +9 -0
- package/rules/js/js/utils-lib-structure.mdc +15 -0
- package/rules/js/main.mdc +19 -211
- package/rules/js/policy/jscpd/jscpd.mdc +14 -0
- package/rules/js/policy/lint_js_yml/lint_js_yml.mdc +14 -0
- package/rules/js/policy/package_json/package_json.mdc +15 -0
- package/rules/js/policy/vscode_extensions/vscode_extensions.mdc +11 -0
- package/rules/js-bun-db/js/bun-sql-migration.mdc +15 -0
- package/rules/js-bun-db/js/connection.mdc +42 -0
- package/rules/js-bun-db/js/pg-format-identifiers.mdc +102 -0
- package/rules/js-bun-db/js/pg-format-shim.mdc +99 -0
- package/rules/js-bun-db/js/pg-leftover.mdc +27 -0
- package/rules/js-bun-db/js/pg-listen-notify.mdc +51 -0
- package/rules/js-bun-db/js/query-safety.mdc +117 -0
- package/rules/js-bun-db/js/sql-array.mdc +88 -0
- package/rules/js-bun-db/js/unsafe.mdc +65 -0
- package/rules/js-bun-db/main.mdc +12 -607
- package/rules/js-bun-db/policy/package_json/package_json.mdc +17 -0
- package/rules/js-bun-redis/js/imports.mdc +47 -0
- package/rules/js-bun-redis/js/package_json.mdc +44 -0
- package/rules/js-bun-redis/main.mdc +4 -10
- package/rules/js-bun-redis/policy/package_json/package_json.mdc +11 -0
- package/rules/js-mssql/js/mssql-in-list.mdc +38 -0
- package/rules/js-mssql/js/mssql-pool.mdc +56 -0
- package/rules/js-mssql/js/mssql-query-template.mdc +33 -0
- package/rules/js-mssql/js/mssql-tvp.mdc +75 -0
- package/rules/js-mssql/js/mssql-version.mdc +7 -0
- package/rules/js-mssql/main.mdc +10 -198
- package/rules/js-mssql/policy/package_json/package_json.mdc +9 -0
- package/rules/js-run/js/check-env.mdc +35 -0
- package/rules/js-run/js/conn-aliases.mdc +109 -0
- package/rules/js-run/js/jsconfig.mdc +20 -0
- package/rules/js-run/js/otel-configmap.mdc +6 -0
- package/rules/js-run/js/pino.mdc +6 -0
- package/rules/js-run/js/project-structure.mdc +11 -0
- package/rules/js-run/js/runtime.mdc +14 -0
- package/rules/js-run/js/scope.mdc +11 -0
- package/rules/js-run/js/settimeout.mdc +11 -0
- package/rules/js-run/js/temporal.mdc +5 -0
- package/rules/js-run/main.mdc +16 -216
- package/rules/js-run/policy/configmap/configmap.mdc +31 -0
- package/rules/js-run/policy/jsconfig/jsconfig.mdc +25 -0
- package/rules/js-run/policy/package_json/package_json.mdc +38 -0
- package/rules/k8s/js/configmap.mdc +41 -0
- package/rules/k8s/js/deployment_resources.mdc +49 -0
- package/rules/k8s/js/hasura_httproute.mdc +91 -0
- package/rules/k8s/js/hpa_apiversion.mdc +27 -0
- package/rules/k8s/js/ingress_gateway.mdc +16 -0
- package/rules/k8s/js/kustomize_structure.mdc +144 -0
- package/rules/k8s/js/lint_k8s.mdc +72 -0
- package/rules/k8s/js/multidoc_yaml.mdc +5 -0
- package/rules/k8s/js/network_policy.mdc +136 -0
- package/rules/k8s/js/schema_modeline.mdc +57 -0
- package/rules/k8s/js/service.mdc +44 -0
- package/rules/k8s/js/topology_hpa_pdb.mdc +181 -0
- package/rules/k8s/main.mdc +29 -834
- package/rules/k8s/policy/base_kustomization/base_kustomization.mdc +12 -0
- package/rules/k8s/policy/base_manifest/base_manifest.mdc +14 -0
- package/rules/k8s/policy/gateway/gateway.mdc +17 -0
- package/rules/k8s/policy/hasura_configmap/hasura_configmap.mdc +20 -0
- package/rules/k8s/policy/hasura_httproute/hasura_httproute.mdc +16 -0
- package/rules/k8s/policy/hpa_pdb/hpa_pdb.mdc +23 -0
- package/rules/k8s/policy/kustomization/kustomization.mdc +20 -0
- package/rules/k8s/policy/manifest/manifest.mdc +17 -0
- package/rules/k8s/policy/network_policy/network_policy.mdc +22 -0
- package/rules/k8s/policy/svc_hl_yaml/svc_hl_yaml.mdc +13 -0
- package/rules/k8s/policy/svc_yaml/svc_yaml.mdc +12 -0
- package/rules/nginx-default-tpl/js/dockerfile.mdc +36 -0
- package/rules/nginx-default-tpl/js/http-route.mdc +41 -0
- package/rules/nginx-default-tpl/js/ini-keys.mdc +21 -0
- package/rules/nginx-default-tpl/js/template-structure.mdc +86 -0
- package/rules/nginx-default-tpl/js/vscode.mdc +37 -0
- package/rules/nginx-default-tpl/main.mdc +8 -110
- package/rules/nginx-default-tpl/policy/vscode_extensions/vscode_extensions.mdc +11 -0
- package/rules/nginx-default-tpl/policy/vscode_settings/vscode_settings.mdc +15 -0
- package/rules/npm-module/js/docs/index.md +5 -5
- package/rules/npm-module/js/docs/rule_meta.md +6 -6
- package/rules/npm-module/js/docs/skill_meta.md +8 -8
- package/rules/npm-module/js/header_doc_pointer.mdc +18 -0
- package/rules/npm-module/js/package_structure.mdc +62 -0
- package/rules/npm-module/js/rule_meta.mdc +11 -0
- package/rules/npm-module/js/skill_meta.mdc +11 -0
- package/rules/npm-module/main.mdc +10 -52
- package/rules/npm-module/policy/emit_types_config/emit_types_config.mdc +40 -0
- package/rules/npm-module/policy/npm_package_json/npm_package_json.mdc +50 -0
- package/rules/npm-module/policy/root_package_json/root_package_json.mdc +37 -0
- package/rules/php/js/lint_php_yml.mdc +12 -0
- package/rules/php/js/tooling.mdc +66 -0
- package/rules/php/main.mdc +5 -66
- package/rules/php/policy/lint_php_yml/lint_php_yml.mdc +21 -0
- package/rules/python/js/lint_python_yml.mdc +23 -0
- package/rules/python/js/pyproject_toml.mdc +32 -0
- package/rules/python/js/tooling.mdc +23 -0
- package/rules/python/main.mdc +7 -32
- package/rules/python/policy/lint_python_yml/lint_python_yml.mdc +12 -0
- package/rules/python/policy/pyproject_toml/pyproject_toml.mdc +13 -0
- package/rules/rego/js/rego-lint.mdc +31 -0
- package/rules/rego/js/vscode_extensions.mdc +11 -0
- package/rules/rego/js/vscode_settings.mdc +13 -0
- package/rules/rego/main.mdc +10 -22
- package/rules/rego/policy/vscode_extensions/vscode_extensions.mdc +11 -0
- package/rules/rego/policy/vscode_settings/vscode_settings.mdc +19 -0
- package/rules/rust/js/coverage.mdc +28 -0
- package/rules/rust/js/lint.mdc +22 -0
- package/rules/rust/js/tauri_composition.mdc +8 -0
- package/rules/rust/js/vscode_extensions.mdc +12 -0
- package/rules/rust/main.mdc +8 -38
- package/rules/rust/policy/lint_rust_yml/lint_rust_yml.mdc +12 -0
- package/rules/rust/policy/vscode_extensions/vscode_extensions.mdc +9 -0
- package/rules/security/js/rego_policies.mdc +15 -0
- package/rules/security/js/sample_secret.mdc +19 -0
- package/rules/security/js/trufflehog.mdc +21 -0
- package/rules/security/main.mdc +7 -34
- package/rules/security/policy/lint_security_yml/lint_security_yml.mdc +7 -0
- package/rules/security/policy/package_json/package_json.mdc +7 -0
- package/rules/style/js/admin-table.mdc +88 -0
- package/rules/style/js/colors.mdc +21 -0
- package/rules/style/js/gap.mdc +22 -0
- package/rules/style/js/quasar-fixes.mdc +32 -0
- package/rules/style/js/quasar.mdc +7 -0
- package/rules/style/js/tooling.mdc +85 -0
- package/rules/style/main.mdc +12 -251
- package/rules/style/policy/lint_style_yml/lint_style_yml.mdc +13 -0
- package/rules/style/policy/package_json/package_json.mdc +18 -0
- package/rules/style/policy/vscode_extensions/vscode_extensions.mdc +13 -0
- package/rules/style/policy/vscode_settings/vscode_settings.mdc +19 -0
- package/rules/tauri/js/cargo_mutants_config.mdc +39 -0
- package/rules/tauri/js/tool_surface.mdc +21 -0
- package/rules/tauri/js/tooling.mdc +25 -0
- package/rules/tauri/main.mdc +6 -78
- package/rules/tauri/policy/vscode_extensions/vscode_extensions.mdc +21 -0
- package/rules/test/js/cargo_mutants_config.mdc +18 -0
- package/rules/test/js/docs/index.md +7 -7
- package/rules/test/js/location.mdc +52 -0
- package/rules/test/js/no-console-store-restore.mdc +11 -0
- package/rules/test/js/no-process-chdir.mdc +15 -0
- package/rules/test/js/no-relative-fs-path.mdc +22 -0
- package/rules/test/js/sandbox-aware-test.mdc +28 -0
- package/rules/test/js/stryker_config.mdc +26 -0
- package/rules/test/js/vitest-config-pool-forks.mdc +33 -0
- package/rules/test/main.mdc +16 -184
- package/rules/test/policy/package_json/package_json.mdc +16 -0
- package/rules/text/js/ci-lint-text.mdc +15 -0
- package/rules/text/js/cspell.mdc +81 -0
- package/rules/text/js/dotenv-linter.mdc +16 -0
- package/rules/text/js/forbidden-prettier.mdc +13 -0
- package/rules/text/js/markdownlint.mdc +25 -0
- package/rules/text/js/oxfmt.mdc +35 -0
- package/rules/text/js/package-json.mdc +26 -0
- package/rules/text/js/shellcheck.mdc +18 -0
- package/rules/text/js/v8r.mdc +23 -0
- package/rules/text/js/vscode.mdc +86 -0
- package/rules/text/main.mdc +20 -231
- package/rules/text/policy/cspell/cspell.mdc +34 -0
- package/rules/text/policy/lint_text/lint_text.mdc +19 -0
- package/rules/text/policy/markdownlint/markdownlint.mdc +38 -0
- package/rules/text/policy/oxfmtrc/oxfmtrc.mdc +11 -0
- package/rules/text/policy/package_json/package_json.mdc +33 -0
- package/rules/text/policy/vscode_extensions/vscode_extensions.mdc +13 -0
- package/rules/text/policy/vscode_settings/vscode_settings.mdc +13 -0
- package/rules/vue/js/composition-api.mdc +82 -0
- package/rules/vue/js/nheader-layout.mdc +171 -0
- package/rules/vue/js/node-imports.mdc +25 -0
- package/rules/vue/js/quasar-ui.mdc +32 -0
- package/rules/vue/js/structure.mdc +101 -0
- package/rules/vue/js/testing.mdc +32 -0
- package/rules/vue/js/tfm-translations.mdc +26 -0
- package/rules/vue/js/vite-config.mdc +126 -0
- package/rules/vue/js/vite-env.mdc +55 -0
- package/rules/vue/js/vue-imports.mdc +25 -0
- package/rules/vue/main.mdc +15 -641
- package/rules/vue/policy/package_json/package_json.mdc +30 -0
- package/scripts/docs/index.md +16 -16
- package/scripts/lib/docs/index.md +36 -36
- package/scripts/utils/docs/index.md +14 -14
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## Перевірки `base/kustomization.yaml`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.base_kustomization`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** `k8s/.../base/kustomization.yaml` (вибір через `isBaseKustomizationPath` у JS; `kind: Kustomization`, `apiVersion: kustomize.config.k8s.io/…`).
|
|
6
|
+
|
|
7
|
+
**Що перевіряється:**
|
|
8
|
+
|
|
9
|
+
- `namespace:` — обов'язковий і непорожній (наприклад `namespace: dev`)
|
|
10
|
+
- `resources:` — не повинен містити `hpa.yaml` або `pdb.yaml` (у будь-якому підкаталозі); HPA/PDB мають бути у sibling-каталозі `components/` і підключатися з overlay через `components: [- ../components]`
|
|
11
|
+
|
|
12
|
+
**Примітка:** рекурсивний обхід `resources:`/`components:`/`bases:` із зануренням у вкладені `kustomization.yaml` — у JS (`verifyK8sBaseKustomizeHasNoHpaPdb`). NetworkPolicy у `base/resources:` — дозволена і не блокується цим правилом.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
## Перевірки маніфестів у шарі `base/`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.base_manifest`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** будь-який `*.yaml` у шляху `k8s/.../base/` (окрім `kustomization.yaml`). JS відбирає файли через `isK8sBaseManifestYamlPath` і передає conftest з цим namespace.
|
|
6
|
+
|
|
7
|
+
**Що перевіряється:**
|
|
8
|
+
|
|
9
|
+
- Namespaced kind — обов'язковий непорожній `metadata.namespace` (cluster-scoped kinds, `List`, `Kustomization` — виняток; список cluster-scoped kinds узгоджено з `CLUSTER_SCOPED_KINDS` у `fix.mjs`)
|
|
10
|
+
- `kind: Deployment` — фіксовані resource-requests у кожному контейнері (включно з `initContainers`):
|
|
11
|
+
- `resources.requests.cpu` рівно `"0.02"` (або число `0.02`)
|
|
12
|
+
- `resources.requests.memory` рівно `"128Mi"` (суфікс `Mi` без урахування регістру)
|
|
13
|
+
|
|
14
|
+
**Примітка:** cross-file перевірки (`metadataNamespaceRequiredViolation` у ширшому контексті дерева) лишаються у JS.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## Перевірки Gateway API маршрутів і HealthCheckPolicy
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.gateway`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** YAML з `kind` одного з: `HTTPRoute`, `GRPCRoute`, `TCPRoute`, `TLSRoute`, `UDPRoute` (`apiVersion: gateway.networking.k8s.io/…`); `HealthCheckPolicy` (`apiVersion: networking.gke.io/…`).
|
|
6
|
+
|
|
7
|
+
**Що перевіряється:**
|
|
8
|
+
|
|
9
|
+
- `HealthCheckPolicy`: `spec.targetRef` обов'язковий; якщо `targetRef.kind` не вказано або `Service` — `targetRef.name` має закінчуватися на `-hl` (headless Service)
|
|
10
|
+
- Gateway API маршрут: кожен `backendRef` до Service (визначається за полями `name` + `port`; `kind`/`group` необов'язкові) — ім'я має закінчуватися на `-hl`
|
|
11
|
+
- Gateway API маршрут: `backendRef` з полем `namespace`, що збігається з `metadata.namespace` маршруту, — заборонено (надлишкове поле, ламається при overlay-перенесеннях)
|
|
12
|
+
|
|
13
|
+
**Приклади:**
|
|
14
|
+
|
|
15
|
+
✓ `backendRef.name: my-svc-hl` (headless)
|
|
16
|
+
✗ `backendRef.name: my-svc` (без суфікса `-hl`)
|
|
17
|
+
✗ `backendRef.namespace: dev` при `metadata.namespace: dev` (redundant)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## Перевірки ConfigMap для Hasura-Deployment
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.hasura_configmap`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** `configmap.yaml` у каталогах, де є Deployment з образом `hasura/graphql-engine`. JS (`manifests.mjs`) знаходить відповідні ConfigMap через cross-file збіг і передає їх conftest з цим namespace.
|
|
6
|
+
|
|
7
|
+
**Що перевіряється (обов'язкові ключі у `data`):**
|
|
8
|
+
|
|
9
|
+
| Ключ | Очікуване значення |
|
|
10
|
+
|------|--------------------|
|
|
11
|
+
| `HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS` | `"true"` |
|
|
12
|
+
| `HASURA_GRAPHQL_ENABLE_RELAY` | `"false"` |
|
|
13
|
+
| `HASURA_GRAPHQL_ENABLE_TELEMETRY` | `"false"` |
|
|
14
|
+
| `HASURA_GRAPHQL_ENABLED_LOG_TYPES` | `"startup,http-log"` (точно) |
|
|
15
|
+
| `HASURA_GRAPHQL_ENABLED_APIS` | `"metadata,graphql,pgdump"` (base/dev; overlay має патчем замінити на `"metadata,graphql"`) |
|
|
16
|
+
| `HASURA_GRAPHQL_DISABLE_EVENTING` | ключ обов'язковий, значення довільне (рекомендовано `"true"`) |
|
|
17
|
+
|
|
18
|
+
Семантика: `"true"`/`"false"` приймаються як boolean або рядок (case-insensitive); точний рядок — exact match.
|
|
19
|
+
|
|
20
|
+
**Примітка:** відбір ConfigMap за сусідством із Hasura-Deployment — cross-file, у JS. Rego — пер-документна валідація полів `data`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
## Перевірки HTTPRoute, парного з Hasura-Deployment
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.hasura_httproute`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** `hr.yaml` (або будь-який HTTPRoute з `kind: HTTPRoute`) у каталогах, де є Deployment з образом `hasura/graphql-engine`. JS знаходить пару Deployment–HTTPRoute через `collectHasuraDeploymentsAndHttpRoutes` і передає conftest з цим namespace.
|
|
6
|
+
|
|
7
|
+
**Що перевіряється — канон 4 правил у `spec.rules` (у порядку):**
|
|
8
|
+
|
|
9
|
+
1. `matches: [{path: {type: Exact, value: "<prefix>/ql"}}]` (без headers) + `filters: [RequestRedirect ReplaceFullPath "<prefix>/ql/console" statusCode 302]`
|
|
10
|
+
2. `matches: [{path: {type: Exact, value: "<prefix>/ql/"}}]` + такий самий redirect на `<prefix>/ql/console`
|
|
11
|
+
3. `matches: [{path: {type: PathPrefix, value: "<prefix>/ql"}}]` + `filters: [URLRewrite ReplacePrefixMatch "/"]` + один `backendRef` на headless Service
|
|
12
|
+
4. WebSocket: `matches: [{path: PathPrefix "<prefix>/ql", headers: [{Exact "Upgrade: websocket"}]}]` + `filters: [URLRewrite ReplacePrefixMatch "/", RequestHeaderModifier remove [Authorization]]` + той самий `backendRef`
|
|
13
|
+
|
|
14
|
+
`<prefix>` визначається автоматично як рядок до `/ql` у першому matching-правилі. Додаткові правила поверх канону дозволені.
|
|
15
|
+
|
|
16
|
+
**Примітка:** cross-file прив'язка HTTPRoute до Deployment — JS (`validateHasuraHttpRouteCanon`).
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
## Структурні перевірки HPA і PDB
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.hpa_pdb`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** `hpa.yaml` (`kind: HorizontalPodAutoscaler`) та `pdb.yaml` (`kind: PodDisruptionBudget`) у overlay-каталогах (не в `base/`).
|
|
6
|
+
|
|
7
|
+
**Що перевіряється:**
|
|
8
|
+
|
|
9
|
+
HPA (`kind: HorizontalPodAutoscaler` або `apiVersion: autoscaling/…`):
|
|
10
|
+
- `apiVersion: autoscaling/v2` (не v1)
|
|
11
|
+
- `kind: HorizontalPodAutoscaler`
|
|
12
|
+
- `spec` — присутній об'єкт
|
|
13
|
+
- `spec.behavior` — присутній; містить `scaleUp` і `scaleDown`, кожен з непорожнім масивом `policies`
|
|
14
|
+
- `spec.metrics` — непорожній масив
|
|
15
|
+
|
|
16
|
+
PDB (`kind: PodDisruptionBudget` або `apiVersion: policy/v1`):
|
|
17
|
+
- `apiVersion: policy/v1`
|
|
18
|
+
- `kind: PodDisruptionBudget`
|
|
19
|
+
- `spec` — присутній об'єкт
|
|
20
|
+
- `spec.selector` — присутній об'єкт
|
|
21
|
+
- `spec.selector.matchLabels` — присутній об'єкт
|
|
22
|
+
|
|
23
|
+
**Примітка:** cross-file перевірки (відповідність `expectedDeployName`, `expectedAppLabel`, `isDevLike`-сегмент) лишаються у JS (`hpaManifestViolations`, `pdbManifestViolations`).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## Структурні перевірки `kustomization.yaml`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.kustomization`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** будь-який `kustomization.yaml` (`kind: Kustomization`, `apiVersion: kustomize.config.k8s.io/…`).
|
|
6
|
+
|
|
7
|
+
**Що перевіряється:**
|
|
8
|
+
|
|
9
|
+
- `resources[]` — має бути масивом рядків; непорожні рядки мають бути відсортовані за алфавітом (en, case-insensitive)
|
|
10
|
+
- `patches[]` — має бути масивом; елементи мають бути відсортовані за tuple `(target.kind, target.name, target.namespace, path)` (case-insensitive)
|
|
11
|
+
- Inline patch (поле `patch` як YAML-рядок JSON6902): у наборі операцій не може бути одночасно `op: remove` і `op: add` на той самий `path` — потрібен `op: replace`
|
|
12
|
+
|
|
13
|
+
**Приклади:**
|
|
14
|
+
|
|
15
|
+
✓ `resources: [deployment.yaml, hpa.yaml, svc.yaml]` (алфавіт)
|
|
16
|
+
✗ `resources: [svc.yaml, deployment.yaml]` (не за алфавітом)
|
|
17
|
+
✓ `op: replace` для зміни значення поля
|
|
18
|
+
✗ `op: remove` + `op: add` на один `path` в одному patch
|
|
19
|
+
|
|
20
|
+
**Примітка:** резолюція kustomize-дерева, перевірка існування refs на диску, парність `svc.yaml`/`svc-hl.yaml` — JS (`rules/k8s/fix.mjs`).
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## Пер-документні перевірки маніфестів Kubernetes
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.manifest`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** будь-який `*.yaml` у шляху з `k8s/` (окрім `kustomization.yaml`, `base/`, `svc.yaml`, `svc-hl.yaml`). Conftest розрізає multi-doc YAML по `---` і запускає policy на кожен документ окремо.
|
|
6
|
+
|
|
7
|
+
**Що перевіряється:**
|
|
8
|
+
|
|
9
|
+
- `kind: Ingress` — заборонено; потрібен Gateway API (HTTPRoute / HealthCheckPolicy)
|
|
10
|
+
- `apiVersion: autoscaling/v1` — заборонено; потрібен `autoscaling/v2`
|
|
11
|
+
- `kind: Service` — анотації `cloud.google.com/neg` та `cloud.google.com/backend-config` заборонені
|
|
12
|
+
- `kind: Deployment` — у кожного контейнера (включно з `initContainers`) обов'язкові `resources.requests.cpu` і `resources.requests.memory` (непорожній рядок або число > 0)
|
|
13
|
+
- `kind: Deployment` з образом `hasura/graphql-engine` — образ має бути у білому списку `allowed_hasura_images` (зараз: `hasura/graphql-engine:v2.49.2.ubuntu.amd64`; `docker.io/` префікс допустимий; digest `@sha256:…` відрізається перед порівнянням)
|
|
14
|
+
- `kind: Deployment` — `spec.strategy.type: RollingUpdate` з `maxUnavailable: 0` і `maxSurge: 1`
|
|
15
|
+
- `kind: Deployment` — канонічний запис у `spec.template.spec.topologySpreadConstraints`: `maxSkew: 1`, `topologyKey: kubernetes.io/hostname`, `whenUnsatisfiable: ScheduleAnyway`, `labelSelector.matchLabels.app: <app-label>` (перевіряється лише для Deployment з міткою `app` у `spec.selector.matchLabels`)
|
|
16
|
+
|
|
17
|
+
**Примітка:** cross-file логіка (Kustomize-резолюція, парність svc/svc-hl, HPA/PDB за каталогом, schema modeline) лишається у JS `rules/k8s/fix.mjs`.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
## Перевірки NetworkPolicy
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.network_policy`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** `networkpolicy.yaml` / будь-який YAML з `kind: NetworkPolicy` або `apiVersion: networking.k8s.io/…`.
|
|
6
|
+
|
|
7
|
+
**Що перевіряється:**
|
|
8
|
+
|
|
9
|
+
- `apiVersion: networking.k8s.io/v1`
|
|
10
|
+
- `kind: NetworkPolicy`
|
|
11
|
+
- `spec` — присутній об'єкт
|
|
12
|
+
- `spec.podSelector.matchLabels` — присутній об'єкт; поле `app` обов'язкове і непорожнє
|
|
13
|
+
- `spec.policyTypes` — містить `Ingress` і `Egress`
|
|
14
|
+
- `spec.ingress` — хоча б одне правило з `from.podSelector`
|
|
15
|
+
- **Superset-перевірка egress/ingress:** кожне правило з канон-сніпета має бути присутнє в `spec.egress` / `spec.ingress` (extra-правила дозволені). Канон обирається за анотацією `nitra.dev/workload-kind`:
|
|
16
|
+
- `StatefulSet` → [stateful-set.snippet.yaml](./template/stateful-set.snippet.yaml) (додає intra-replica ingress/egress)
|
|
17
|
+
- решта (default) → [deployment.snippet.yaml](./template/deployment.snippet.yaml)
|
|
18
|
+
- Заборонено `egress: [{}]` (allow-all) — навіть як extra-правило
|
|
19
|
+
|
|
20
|
+
**Передача snippets:** через `--data` при виклику conftest (JS передає `templateData` для `runConftestBatch`).
|
|
21
|
+
|
|
22
|
+
**Примітка:** cross-file визначення `metadata.name` воркнавантаження і мітки `app` — JS (`validateNetworkPolicyForWorkload`).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## Перевірки `svc-hl.yaml` (Headless Service)
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.svc_hl_yaml`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** лише `svc-hl.yaml` (basename). JS відбирає файли через walk по `basename == "svc-hl.yaml"`.
|
|
6
|
+
|
|
7
|
+
**Що перевіряється:**
|
|
8
|
+
|
|
9
|
+
- `kind: Service` — `metadata.name` має закінчуватися на `-hl`
|
|
10
|
+
- `kind: Service` — `spec.clusterIP` має бути `None` (headless)
|
|
11
|
+
|
|
12
|
+
✓ `metadata.name: my-app-hl`, `spec.clusterIP: None`
|
|
13
|
+
✗ `metadata.name: my-app` (без суфікса), `spec.clusterIP: 10.0.0.1`
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## Перевірки `svc.yaml` (ClusterIP Service)
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `k8s.svc_yaml`
|
|
4
|
+
|
|
5
|
+
**Цільові файли:** лише `svc.yaml` (basename). JS відбирає файли через walk по `basename == "svc.yaml"` і передає conftest з цим namespace.
|
|
6
|
+
|
|
7
|
+
**Що перевіряється:**
|
|
8
|
+
|
|
9
|
+
- `kind: Service` — `spec.type` має бути `ClusterIP` (відсутній `spec` або `type != "ClusterIP"` — порушення)
|
|
10
|
+
|
|
11
|
+
✓ `spec.type: ClusterIP`
|
|
12
|
+
✗ `spec.type: LoadBalancer` або відсутній `spec`
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
## Dockerfile — стиснення статики та envsubst шаблону
|
|
2
|
+
|
|
3
|
+
Dockerfile потребує двох кроків, пов'язаних з nginx-шаблоном.
|
|
4
|
+
|
|
5
|
+
### Стиснення статики (gzip_static)
|
|
6
|
+
|
|
7
|
+
Щоб nginx міг використовувати `gzip_static on`, файли необхідно стиснути під час збирання образу:
|
|
8
|
+
|
|
9
|
+
```dockerfile
|
|
10
|
+
RUN find /usr/share/nginx/html -type f \( \
|
|
11
|
+
-name '*.js' -o -name '*.css' -o -name '*.map' -o -name '*.xml' -o \
|
|
12
|
+
-name '*.webmanifest' -o -name '*.html' -o -name '*.wasm' -o -name '*.ttf' \
|
|
13
|
+
\) -exec gzip -k {} +
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Прапорець `-k` зберігає оригінальний файл поруч зі стиснутим `.gz`.
|
|
17
|
+
|
|
18
|
+
### envsubst для default.conf.template
|
|
19
|
+
|
|
20
|
+
Для підстановки змінних середовища у шаблон:
|
|
21
|
+
|
|
22
|
+
```dockerfile
|
|
23
|
+
# 1) Витягнути імена змінних з ini (ігноруємо коментарі/порожні)
|
|
24
|
+
# 2) Зробити список для envsubst: $NAMESPACE $NAMESPACE2 ...
|
|
25
|
+
# 3) Підвантажити значення з ini і підставити лише їх
|
|
26
|
+
RUN NAMES=$(sed -nE '/^\s*[#;]/d; /^\s*$/d; s/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=.*/\1/p' /tpl/values-$BRANCH.ini) && \
|
|
27
|
+
VARS=$(printf '%s\n' $NAMES | awk '{printf "$%s ", $0}') && \
|
|
28
|
+
export $(grep -v '^#' /tpl/values-$BRANCH.ini | xargs) && \
|
|
29
|
+
envsubst "$VARS" < /tpl/default.conf.template > /app/default.conf
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Перевірки (автоматичні):
|
|
33
|
+
|
|
34
|
+
- Dockerfile містить `find … /usr/share/nginx/html … gzip -k` — крок стиснення статики
|
|
35
|
+
- Dockerfile містить `envsubst` і посилання на `default.conf.template`
|
|
36
|
+
- Якщо немає жодного Dockerfile / Containerfile поруч з `default.conf.template` — це помилка
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
## HTTPRoute в k8s — редирект і backendRefs
|
|
2
|
+
|
|
3
|
+
Якщо в `default.conf.template` були `proxy_pass`-секції — їхню логіку потрібно перенести
|
|
4
|
+
до HTTPRoute в k8s. `default.conf.template` **не повинен** містити жодного proxy.
|
|
5
|
+
|
|
6
|
+
HTTPRoute має містити два правила:
|
|
7
|
+
|
|
8
|
+
1. **Exact → RequestRedirect 301 (https)** — редирект з `/$PUBLIC_PATH` на `/$PUBLIC_PATH/`
|
|
9
|
+
2. **PathPrefix → backendRefs:8080** — проксі трафіку на сервіс
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
spec:
|
|
13
|
+
rules:
|
|
14
|
+
- matches:
|
|
15
|
+
- path:
|
|
16
|
+
type: Exact
|
|
17
|
+
value: /$PUBLIC_PATH
|
|
18
|
+
filters:
|
|
19
|
+
- type: RequestRedirect
|
|
20
|
+
requestRedirect:
|
|
21
|
+
scheme: https
|
|
22
|
+
path:
|
|
23
|
+
type: ReplaceFullPath
|
|
24
|
+
replaceFullPath: /$PUBLIC_PATH/
|
|
25
|
+
statusCode: 301
|
|
26
|
+
- matches:
|
|
27
|
+
- path:
|
|
28
|
+
type: PathPrefix
|
|
29
|
+
value: /$PUBLIC_PATH/
|
|
30
|
+
backendRefs:
|
|
31
|
+
- name: $SERVICE_NAME
|
|
32
|
+
port: 8080
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
де `$PUBLIC_PATH` підставляється з ini-файлу dev-середовища, а для інших середовищ — через `kustomization.yaml`.
|
|
36
|
+
`$SERVICE_NAME` — ім'я k8s-сервісу, що приймає трафік на порту 8080.
|
|
37
|
+
|
|
38
|
+
Перевірки (автоматичні):
|
|
39
|
+
|
|
40
|
+
- перше правило має `path.type: Exact` і фільтр `RequestRedirect` з `scheme: https`, `path.type: ReplaceFullPath`, `statusCode: 301`
|
|
41
|
+
- друге правило має `path.type: PathPrefix` і `backendRefs` з `port: 8080`
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## Конфігураційні *.ini файли і envsubst
|
|
2
|
+
|
|
3
|
+
Поруч з `default.conf.template` мають бути конфігураційні файли `*.ini` для кожного
|
|
4
|
+
середовища (наприклад, `values-dev.ini`, `values-prod.ini`).
|
|
5
|
+
|
|
6
|
+
Формат ini-файлу:
|
|
7
|
+
|
|
8
|
+
```ini
|
|
9
|
+
PUBLIC_PATH=/app
|
|
10
|
+
SERVICE_NAME=my-frontend
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Кожна змінна з `*.ini` **повинна використовуватись** у `default.conf.template` як `$KEY`
|
|
14
|
+
(через envsubst). Якщо у `*.ini` є ключ, що відсутній у шаблоні — його треба вилучити з ini
|
|
15
|
+
або додати в шаблон.
|
|
16
|
+
|
|
17
|
+
Перевірки (автоматичні):
|
|
18
|
+
|
|
19
|
+
- Поруч з кожним `default.conf.template` є щонайменше один `*.ini` файл
|
|
20
|
+
- Кожен ключ з `*.ini` (рядки виду `KEY=value`, без коментарів `#`/`;` і порожніх рядків)
|
|
21
|
+
присутній у шаблоні як `$KEY`
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
## Канонічна структура default.conf.template
|
|
2
|
+
|
|
3
|
+
`default.conf.template` — єдиний nginx-конфіг для фронтенду зі статичними файлами.
|
|
4
|
+
Він **не повинен** містити жодних `proxy_pass`, `proxy_redirect`, `proxy_set_header`,
|
|
5
|
+
`fastcgi_pass`, `grpc_pass`, `uwsgi_pass`. Усю проксі-логіку потрібно винести в HTTPRoute (k8s).
|
|
6
|
+
|
|
7
|
+
Канонічний вигляд файлу:
|
|
8
|
+
|
|
9
|
+
```nginx
|
|
10
|
+
server_tokens off;
|
|
11
|
+
port_in_redirect off;
|
|
12
|
+
client_max_body_size 0;
|
|
13
|
+
client_body_buffer_size 512M;
|
|
14
|
+
|
|
15
|
+
server {
|
|
16
|
+
listen 8080;
|
|
17
|
+
server_name _;
|
|
18
|
+
|
|
19
|
+
# disable all log
|
|
20
|
+
access_log off;
|
|
21
|
+
# `error_log off;` — НЕ валідний nginx: "off" трактується як ім'я файлу (/etc/nginx/off)
|
|
22
|
+
# і падає під readOnlyRootFilesystem. /dev/null — writable device.
|
|
23
|
+
error_log /dev/null crit;
|
|
24
|
+
|
|
25
|
+
# This would be the directory where your Vite app's static files are stored at
|
|
26
|
+
root /usr/share/nginx/html;
|
|
27
|
+
|
|
28
|
+
location /healthz {
|
|
29
|
+
add_header Content-Type text/plain;
|
|
30
|
+
access_log off;
|
|
31
|
+
return 200 "healthy";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Без gz стиснених файлів, 1 year is 31536000 seconds
|
|
35
|
+
location ~ ^$PUBLIC_PATH/(.+\.(?:gif|jpe?g|png|ico|woff2|xlsx))$ {
|
|
36
|
+
alias /usr/share/nginx/html/$1;
|
|
37
|
+
add_header 'Cache-Control' "public,max-age=31536000,immutable";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# С gz стисненими файлами, 1 year is 31536000 seconds
|
|
41
|
+
location ~ ^$PUBLIC_PATH/(.+\.(?:svg|js|css|ttf|map|xml|webmanifest|wasm))$ {
|
|
42
|
+
alias /usr/share/nginx/html/$1;
|
|
43
|
+
add_header 'Cache-Control' "public,max-age=31536000,immutable";
|
|
44
|
+
|
|
45
|
+
# дозволяє віддавати замість звичайного файлу попередньо стиснутий файл з таким же ім'ям та з розширенням ".gz"
|
|
46
|
+
gzip_static on;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
location $PUBLIC_PATH/ {
|
|
50
|
+
index index.html;
|
|
51
|
+
alias /usr/share/nginx/html/;
|
|
52
|
+
|
|
53
|
+
# eliminates the step of copying the data into the buffer and enables direct copying data from one file descriptor to another.
|
|
54
|
+
sendfile on;
|
|
55
|
+
# to prevent one fast connection from entirely occupying the worker process
|
|
56
|
+
sendfile_max_chunk 512k;
|
|
57
|
+
# to send HTTP response headers in one packet right after the chunk of data has been obtained by sendfile().
|
|
58
|
+
tcp_nopush on;
|
|
59
|
+
|
|
60
|
+
# дозволяє віддавати замість звичайного файлу попередньо стиснутий файл з таким же ім'ям та з розширенням ".gz"
|
|
61
|
+
gzip_static on;
|
|
62
|
+
|
|
63
|
+
try_files $uri $uri/ /index.html =404;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Обов'язкові вимоги до структури (перевіряються автоматично):
|
|
69
|
+
|
|
70
|
+
- `server_tokens off` — приховує версію nginx у відповідях
|
|
71
|
+
- `port_in_redirect off` — виключає порт з redirect-заголовків
|
|
72
|
+
- `client_max_body_size 0` — без ліміту тіла запиту
|
|
73
|
+
- `client_body_buffer_size 512M`
|
|
74
|
+
- `listen 8080`
|
|
75
|
+
- `server_name _` — catch-all
|
|
76
|
+
- `access_log off`
|
|
77
|
+
- `error_log /dev/null crit` (НЕ `error_log off;` — це некоректно в nginx)
|
|
78
|
+
- `root /usr/share/nginx/html`
|
|
79
|
+
- `location /healthz` з `return 200` і рядком `healthy`
|
|
80
|
+
- location для статики без gzip (`gif|jpeg|png|ico|woff2|xlsx`) з `Cache-Control: max-age=31536000,immutable`
|
|
81
|
+
- location для статики з gzip (`svg|js|css|ttf|map|xml|webmanifest|wasm`) з `gzip_static on`
|
|
82
|
+
- `gzip_static on` щонайменше двічі (два location зі стисненням)
|
|
83
|
+
- `$PUBLIC_PATH` у location — плейсхолдер підставляється через envsubst
|
|
84
|
+
- `sendfile on`, `sendfile_max_chunk 512k`, `tcp_nopush on`
|
|
85
|
+
- `try_files $uri $uri/ /index.html =404`
|
|
86
|
+
- **Відсутність** будь-якого `proxy_pass` / `fastcgi_pass` / `grpc_pass` / `uwsgi_pass`
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
## VS Code — розширення та налаштування nginx
|
|
2
|
+
|
|
3
|
+
Коли у проєкті є `default.conf.template`, очікуються відповідні VS Code конфігурації
|
|
4
|
+
для підтримки nginx-синтаксису.
|
|
5
|
+
|
|
6
|
+
### .vscode/extensions.json
|
|
7
|
+
|
|
8
|
+
`recommendations` має містити розширення `ahmadalli.vscode-nginx-conf`:
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{
|
|
12
|
+
"recommendations": [
|
|
13
|
+
"ahmadalli.vscode-nginx-conf"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### .vscode/settings.json
|
|
19
|
+
|
|
20
|
+
Має бути увімкнений `formatOnSave` і встановлений форматер nginx:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"editor.formatOnSave": true,
|
|
25
|
+
"[nginx]": {
|
|
26
|
+
"editor.defaultFormatter": "ahmadalli.vscode-nginx-conf"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Перевірки виконуються через Rego-пакети (conftest):
|
|
32
|
+
|
|
33
|
+
- `nginx_default_tpl.vscode_extensions` — перевіряє наявність `ahmadalli.vscode-nginx-conf` у `recommendations`
|
|
34
|
+
- `nginx_default_tpl.vscode_settings` — перевіряє `editor.formatOnSave: true` і `[nginx].editor.defaultFormatter: "ahmadalli.vscode-nginx-conf"`
|
|
35
|
+
|
|
36
|
+
Ці перевірки активуються **лише** якщо в проєкті знайдено `default.conf.template`
|
|
37
|
+
(умовне правило, не auto-discoverable без JS-gate).
|
|
@@ -5,120 +5,18 @@ globs: "**/default.{conf.template,tpl.conf}"
|
|
|
5
5
|
alwaysApply: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
default.conf.template
|
|
8
|
+
Правило забезпечує відповідність `default.conf.template` канонічній структурі nginx для фронтенду зі статичними файлами, а також перевіряє пов'язані артефакти: HTTPRoute (k8s), Dockerfile, ini-файли середовищ і VS Code конфігурацію.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
server_tokens off;
|
|
12
|
-
port_in_redirect off;
|
|
13
|
-
client_max_body_size 0;
|
|
14
|
-
client_body_buffer_size 512M;
|
|
10
|
+
[nginx-default-tpl-template-structure](./js/template-structure.mdc)
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
listen 8080;
|
|
18
|
-
server_name _;
|
|
12
|
+
[nginx-default-tpl-http-route](./js/http-route.mdc)
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
access_log off;
|
|
22
|
-
# `error_log off;` — НЕ валідний nginx: "off" трактується як ім'я файлу (/etc/nginx/off)
|
|
23
|
-
# і падає під readOnlyRootFilesystem. /dev/null — writable device.
|
|
24
|
-
error_log /dev/null crit;
|
|
14
|
+
[nginx-default-tpl-dockerfile](./js/dockerfile.mdc)
|
|
25
15
|
|
|
26
|
-
|
|
27
|
-
root /usr/share/nginx/html;
|
|
16
|
+
[nginx-default-tpl-ini-keys](./js/ini-keys.mdc)
|
|
28
17
|
|
|
29
|
-
|
|
30
|
-
add_header Content-Type text/plain;
|
|
31
|
-
access_log off;
|
|
32
|
-
return 200 "healthy";
|
|
33
|
-
}
|
|
18
|
+
[nginx-default-tpl-vscode](./js/vscode.mdc)
|
|
34
19
|
|
|
35
|
-
|
|
36
|
-
location ~ ^$PUBLIC_PATH/(.+\.(?:gif|jpe?g|png|ico|woff2|xlsx))$ {
|
|
37
|
-
alias /usr/share/nginx/html/$1;
|
|
38
|
-
add_header 'Cache-Control' "public,max-age=31536000,immutable";
|
|
39
|
-
}
|
|
20
|
+
[nginx-default-tpl-vscode_extensions](./policy/vscode_extensions/vscode_extensions.mdc)
|
|
40
21
|
|
|
41
|
-
|
|
42
|
-
location ~ ^$PUBLIC_PATH/(.+\.(?:svg|js|css|ttf|map|xml|webmanifest|wasm))$ {
|
|
43
|
-
alias /usr/share/nginx/html/$1;
|
|
44
|
-
add_header 'Cache-Control' "public,max-age=31536000,immutable";
|
|
45
|
-
|
|
46
|
-
# дозволяє віддавати замість звичайного файлу попередньо стиснутий файл з таким же ім'ям та з розширенням ".gz"
|
|
47
|
-
gzip_static on;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
location $PUBLIC_PATH/ {
|
|
51
|
-
index index.html;
|
|
52
|
-
alias /usr/share/nginx/html/;
|
|
53
|
-
|
|
54
|
-
# eliminates the step of copying the data into the buffer and enables direct copying data from one file descriptor to another.
|
|
55
|
-
sendfile on;
|
|
56
|
-
# to prevent one fast connection from entirely occupying the worker process
|
|
57
|
-
sendfile_max_chunk 512k;
|
|
58
|
-
# to send HTTP response headers in one packet right after the chunk of data has been obtained by sendfile().
|
|
59
|
-
tcp_nopush on;
|
|
60
|
-
|
|
61
|
-
# дозволяє віддавати замість звичайного файлу попередньо стиснутий файл з таким же ім'ям та з розширенням ".gz"
|
|
62
|
-
gzip_static on;
|
|
63
|
-
|
|
64
|
-
try_files $uri $uri/ /index.html =404;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Тобто в ньому не потрібно щоб було жодного proxy_pass секціі і інших опцій для proxy.
|
|
70
|
-
|
|
71
|
-
Якщо в файлі вже були proxy_pass секції, то їх логіку потрібно перенести до HTTPRoute в k8s.
|
|
72
|
-
|
|
73
|
-
В HTTPRoute повинна бути секція Exact редиректу на версію з /
|
|
74
|
-
|
|
75
|
-
```yaml
|
|
76
|
-
spec:
|
|
77
|
-
rules:
|
|
78
|
-
- matches:
|
|
79
|
-
- path:
|
|
80
|
-
type: Exact
|
|
81
|
-
value: /$PUBLIC_PATH
|
|
82
|
-
filters:
|
|
83
|
-
- type: RequestRedirect
|
|
84
|
-
requestRedirect:
|
|
85
|
-
scheme: https
|
|
86
|
-
path:
|
|
87
|
-
type: ReplaceFullPath
|
|
88
|
-
replaceFullPath: /$PUBLIC_PATH/
|
|
89
|
-
statusCode: 301
|
|
90
|
-
- matches:
|
|
91
|
-
- path:
|
|
92
|
-
type: PathPrefix
|
|
93
|
-
value: /$PUBLIC_PATH/
|
|
94
|
-
backendRefs:
|
|
95
|
-
- name: $SERVICE_NAME
|
|
96
|
-
port: 8080
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
де $PUBLIC_PATH підставляється з ini файлу з dev середовища, а якщо для інших середовищ відрізняється то підставляється в kustomization.yaml відповідні значення з ini середовища.
|
|
100
|
-
|
|
101
|
-
В $SERVICE_NAME повинно бути вказано ім'я сервісу, яке буде використовуватися в k8s.
|
|
102
|
-
|
|
103
|
-
В Dockerfile потрібно додати команду для стиснення файлів, які потім використовуватимуться з `gzip_static on`:
|
|
104
|
-
|
|
105
|
-
```dockerfile
|
|
106
|
-
RUN find /usr/share/nginx/html -type f \( \
|
|
107
|
-
-name '*.js' -o -name '*.css' -o -name '*.map' -o -name '*.xml' -o \
|
|
108
|
-
-name '*.webmanifest' -o -name '*.html' -o -name '*.wasm' -o -name '*.ttf' \
|
|
109
|
-
\) -exec gzip -k {} +
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Поруч з файлом default.conf.template повинні бути конфігураційні файли *.ini для різних середовищ. В Dockerfile повинна бути команда, для заміни плейсхолдерів в цих файлах на значення з середовища:
|
|
113
|
-
|
|
114
|
-
```dockerfile
|
|
115
|
-
# 1) Витягнути імена змінних з ini (ігноруємо коментарі/порожні)
|
|
116
|
-
# 2) Зробити список для envsubst: $NAMESPACE $NAMESPACE2 ...
|
|
117
|
-
# 3) Підвантажити значення з ini і підставити лише їх
|
|
118
|
-
RUN NAMES=$(sed -nE '/^\s*[#;]/d; /^\s*$/d; s/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=.*/\1/p' /tpl/values-$BRANCH.ini) && \
|
|
119
|
-
VARS=$(printf '%s\n' $NAMES | awk '{printf "$%s ", $0}') && \
|
|
120
|
-
export $(grep -v '^#' /tpl/values-$BRANCH.ini | xargs) && \
|
|
121
|
-
envsubst "$VARS" < /tpl/default.conf.template > /app/default.conf
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Якщо у конфігураційних файлах *.ini є змінні які відсутні в default.conf.template, то їх потрібно вилучити.
|
|
22
|
+
[nginx-default-tpl-vscode_settings](./policy/vscode_settings/vscode_settings.mdc)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Rego-gate: наявність розширення nginx у `.vscode/extensions.json`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `nginx_default_tpl.vscode_extensions`
|
|
4
|
+
|
|
5
|
+
Цільовий файл: `.vscode/extensions.json`
|
|
6
|
+
|
|
7
|
+
Перевіряє, що масив `recommendations` містить рядок `"ahmadalli.vscode-nginx-conf"`. Відсутнє поле `recommendations` або порожній масив — теж deny.
|
|
8
|
+
|
|
9
|
+
✓ `{"recommendations": ["ahmadalli.vscode-nginx-conf"]}`
|
|
10
|
+
✗ `{"recommendations": []}` — розширення відсутнє
|
|
11
|
+
✗ `{}` — поле `recommendations` відсутнє
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## Rego-gate: налаштування форматера nginx у `.vscode/settings.json`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `nginx_default_tpl.vscode_settings`
|
|
4
|
+
|
|
5
|
+
Цільовий файл: `.vscode/settings.json`
|
|
6
|
+
|
|
7
|
+
Три незалежні deny-правила:
|
|
8
|
+
|
|
9
|
+
1. `"editor.formatOnSave"` має бути `true` (відсутність або `false` → deny).
|
|
10
|
+
2. `"[nginx]"` має бути обʼєктом (рядок або відсутність → deny).
|
|
11
|
+
3. `"[nginx].editor.defaultFormatter"` має дорівнювати `"ahmadalli.vscode-nginx-conf"`.
|
|
12
|
+
|
|
13
|
+
✓ `{"editor.formatOnSave": true, "[nginx]": {"editor.defaultFormatter": "ahmadalli.vscode-nginx-conf"}}`
|
|
14
|
+
✗ `{"editor.formatOnSave": false, "[nginx]": {"editor.defaultFormatter": "ahmadalli.vscode-nginx-conf"}}` — formatOnSave не true
|
|
15
|
+
✗ `{"editor.formatOnSave": true, "[nginx]": "ahmadalli.vscode-nginx-conf"}` — `[nginx]` не обʼєкт
|
|
@@ -6,9 +6,9 @@ resource: npm/rules/npm-module/js/
|
|
|
6
6
|
|
|
7
7
|
# npm/rules/npm-module/js
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------- | --------- |
|
|
11
11
|
| [header_doc_pointer.mjs](header_doc_pointer.md) | JS Module |
|
|
12
|
-
| [package_structure.mjs](package_structure.md)
|
|
13
|
-
| [rule_meta.mjs](rule_meta.md)
|
|
14
|
-
| [skill_meta.mjs](skill_meta.md)
|
|
12
|
+
| [package_structure.mjs](package_structure.md) | JS Module |
|
|
13
|
+
| [rule_meta.mjs](rule_meta.md) | JS Module |
|
|
14
|
+
| [skill_meta.mjs](skill_meta.md) | JS Module |
|
|
@@ -17,12 +17,12 @@ docgen:
|
|
|
17
17
|
1. Перевіряє наявність каталогу `npm/rules` у корені репозиторію. Якщо каталог відсутній, завершує роботу, повідомляючи про відсутність правил для валідації.
|
|
18
18
|
2. Ітерує по всім підкаталогах у `npm/rules`, ігноруючи приховані каталоги.
|
|
19
19
|
3. Для кожного каталогу виконує перевірку правила:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
а. Перевіряє відсутність файлу `auto.md`. Якщо знайдено, повідомляє про залишковий файл.
|
|
21
|
+
б. Перевіряє наявність файлу `main.mdc`. Якщо відсутній, повідомляє про відсутність обов'язкового файлу (scripts.mdc).
|
|
22
|
+
в. Зчитує вміст `main.json` каталогу правила. Якщо файл відсутній або невалідний, повідомляє про це та пропускає подальшу валідацію цього правила.
|
|
23
|
+
г. Перевіряє поле `auto` у `main.json`. Якщо поле присутнє, валідує його структуру та перевіряє, чи всі використані предикати визначені.
|
|
24
|
+
ґ. Перевіряє поле `lint` у `main.json`. Якщо поле присутнє, валідує його структуру та перевіряє, чи експортує файл `main.mjs` відповідну функцію `lint`.
|
|
25
|
+
і. Якщо всі перевірки для правила пройдені успішно, повідомляє про валідність `main.json`.
|
|
26
26
|
4. Після обробки всіх правил повертає код виходу, що відображає загальний статус валідації.
|
|
27
27
|
|
|
28
28
|
## Публічний API
|