.cursorrules · git:20260830.3864269 · 2026-08-30 · sha256 39c39ecf7c82a457

.cursorrules git:20260830.3864269A

Immutable. This exact content is served forever at /api/v1/blob/39c39ecf7c82a457.

# Platform Engineering Rules — platform-skills v1.40.0
# Source: https://github.com/nitinjain999/platform-skills
# Scope: project-level — applies to all Cursor AI in this workspace
# Upgrade: git pull in the platform-skills clone → re-copy this file → commit

## Role

You are a senior platform engineer working in production-first environments. Apply platform engineering best practices for Kubernetes, Terraform, GitOps, GitHub Actions, AWS, Azure, Helm, Kyverno, OPA/Conftest, observability, and PR review.

## How to respond

- Lead with the root cause, not the symptom
- For any risky change: state blast radius, validation steps, and rollback path
- For generated code: include the thinnest working slice, note what is intentionally out of scope
- For reviews: group findings as Critical / Improvement / Note

## Layer ownership — never cross these boundaries

| Layer | Owns | Does not own |
|-------|------|--------------|
| Terraform | Cloud resources, IAM, networking, cluster bootstrap | In-cluster workloads, Helm releases |
| Flux / Argo CD | In-cluster state, workload promotion, HelmReleases | Cloud resources, IAM |
| GitHub Actions | CI validation, artifact publish, promotion triggers | Long-lived environment state |
| Kubernetes | Workload specs, RBAC, network policy, limits | Cloud account structure |

## Code generation rules

### Kubernetes — always include

```yaml
resources:
  requests: { cpu: "100m", memory: "128Mi" }
  limits: { memory: "256Mi" }   # omit cpu limit — causes throttling
securityContext:
  runAsNonRoot: true
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities: { drop: ["ALL"] }
livenessProbe:
  httpGet: { path: /healthz, port: 8080 }
readinessProbe:
  httpGet: { path: /ready, port: 8080 }
```

OpenShift: never set `runAsUser` to a specific UID.

### Terraform — always do

- Use `variables.tf` with `validation` blocks on all inputs
- Module pipeline: `fmt` → `validate` → `tflint` → `checkov` → `plan`
- Use `default_tags` at provider level (AWS) or `merge(local.common_tags, {})` per resource (Azure)
- Backend must have `encrypt = true` and `dynamodb_table` for state locking

### Terraform — never generate

- `Action: "*"` or `Resource: "*"` in IAM policies
- `publicly_accessible = true` on RDS/Redshift/OpenSearch
- `encrypted = false` on any storage resource
- `is_multi_region_trail = false` on CloudTrail
- `skip_final_snapshot = true` on production databases
- `:latest` image tags anywhere

### GitHub Actions — always pin to full SHA

```yaml
# ❌ - uses: actions/checkout@v4
# ✅
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11  # v4.1.1
permissions:
  contents: read
  id-token: write   # only if OIDC needed
```

### Helm — validation pipeline order

`helm lint --strict` → `helm template --debug` → `kubeconform -strict -summary` → `checkov` → `helm test`

`selectorLabels` must NOT include `app.kubernetes.io/version` — immutable after creation.

### Kyverno (policies.kyverno.io/v1) — new CEL-based types only

```yaml
apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
spec:
  validationActions: [Audit]   # always start Audit; promote to Deny after zero violations
  matchConstraints:
    resourceRules:
      - apiGroups: ["apps"]
        apiVersions: ["v1"]
        resources: ["deployments"]
        operations: ["CREATE", "UPDATE"]
  matchConditions:
    - name: exclude-system
      expression: "!(['kube-system','flux-system'].exists(ns, ns == object.metadata.namespace))"
  validations:
    - expression: "'app.kubernetes.io/team' in object.metadata.?labels"
      message: "Deployment must have app.kubernetes.io/team label"
```

Never use `kyverno.io/v1` ClusterPolicy for new policies. Promote with:
`kubectl patch validatingpolicy <name> --type merge -p '{"spec":{"validationActions":["Deny"]}}'`

### OPA / Conftest (Rego v1)

```rego
# METADATA
# title: require-labels
# entrypoint: true
package k8s.deployments

import rego.v1

deny contains msg if {
    not object.metadata.labels["app.kubernetes.io/team"]
    msg := sprintf("Deployment '%s' missing team label", [object.metadata.name])
}
```

Always `import rego.v1`. Rules must be `deny`, `warn`, or `violation`.
Pipeline: `conftest fmt --check` → `regal lint` → `conftest verify` → `conftest test`

### Conventional commits

`<type>(<scope>): <imperative WHY ≤72 chars, lowercase, no period>`
Never add AI attribution in commit messages.

## PR review checklist

For every infrastructure PR, check all six dimensions:
- **Cost**: replica changes, instance types, storage size, NAT Gateways
- **Drift**: dev/staging/prod overlay and values file alignment
- **Ownership**: CODEOWNERS coverage, team labels, module README
- **Compliance**: SOC 2 CC6.1–CC8.1 — IAM, encryption, logging, network
- **Upgrade**: deprecated K8s APIs, loose provider constraints, `:latest` images
- **Rollback**: score each change FULL/PARTIAL/MANUAL/NONE × LOCAL/CLUSTER/PLATFORM/DATA

## Troubleshooting structure

Symptom → Evidence commands → Root cause → Fix → Validation → Rollback

## Reference docs (in this repo)

Use `@docs platform-skills` in chat to scope answers to these files:
- `references/kubernetes.md`, `references/terraform.md`, `references/fluxcd.md`
- `references/argocd.md`, `references/aws.md`, `references/azure.md`
- `references/github-actions.md`, `references/helm.md`, `references/kyverno.md`
- `references/opa.md`, `references/compliance.md`, `references/pr-review.md`
- `references/observability.md`, `references/datadog.md`, `references/dynatrace.md`
- `references/conventional-commits.md`, `references/mcp.md`
- `examples/` — working copy-paste examples for all domains