nic-planning
nginx/kubernetes-ingress/.github/skills/nic-planning/SKILL.md
Task planning and approach strategy for NIC. Use when starting any non-trivial task, reading issues or specs, planning before implementing, or when asked to create a plan for a change.
Skill5.1k starsChanged 22 days ago
What's in it
- Planning and Task Approach
- Before Writing Code
- Layer Impact Checklist
- Definition of Done
- Scope Assessment
- Common Planning Mistakes
- Ordering Rules for Multi-Layer Changes
--- name: nic-planning description: 'Task planning and approach strategy for NIC. Use when starting any non-trivial task, reading issues or specs, planning before implementing, or when asked to create a plan for a change.' --- # Planning and Task Approach ## Before Writing Code 1. **Read the requirement** — Understand what's being asked. Check linked issues, specs, or PRs for full context. 2. **Write acceptance criteria** — Before implementing, state what "done" looks like in testable terms. What should work? What should be rejected? What must NOT break? 3. **Identify security impact** — Does this change: - Accept new external/untrusted input? → Requires input validation at the trust boundary - Touch credential or secret paths? → Requires human review - Generate config from user data? → Must pass through `containsDangerousChars()` - Change RBAC or access control? → Requires security review 4. **Identify affected layers** — Determine which architectural layers are touched: - Data Model (`pkg/apis/configuration/v1/types.go`) - Validation (`pkg/apis/configuration/validation/`) - Controller (`internal/k8s/`) - Config Generation (`internal/configs/`) - Templates (`internal/configs/version1/` or `version2/`) - Process Management (`internal/nginx/`) - Helm Chart (`charts/nginx-ingress/`) 5. **Check invariants** — Review the Key Invariants section in AGENTS.md: - Security: `containsDangerousChars()` on user strings reaching NGINX config - Codegen: Never edit `zz_generated.deepcopy.go` manually - Templates: Update BOTH OSS and Plus variants for shared directives; Plus-only directives go in the Plus template only - CRD fields: Every new field needs kubebuilder markers + validation + template + tests 6. **Identify test surface** — What tests need adding or updating? - Unit tests for validation logic - Negative tests for input rejection (security) - Snapshot tests for template output - Helm tests if chart changes - Integration tests if behaviour changes 7. **Produce a plan** — State your approach before coding. List files to change in order. Include what this change must NOT break. ## Layer Impact Checklist For any change, ask: - [ ] Does it accept new external input? → Add validation with `containsDangerousChars()` or appropriate sanitizer - [ ] Does it touch `types.go`? → Run `make update-codegen` then `make update-crds` - [ ] Does it add a template directive? → Update BOTH `nginx.ingress.tmpl` AND `nginx-plus.ingress.tmpl` (or v2 equivalents) if the directive is shared; Plus-only directives go in the Plus template alone - [ ] Does it add a CRD field? → Add kubebuilder markers, validation, template struct, rendering, tests - [ ] Does it touch Helm values? → Update `values.yaml`, `values.schema.json`, and helmunit tests - [ ] Does it affect config generation? → Add a snapshot fixture that exercises the change, then run `make test-update-snaps` - [ ] Does it change telemetry data types? → Run `make telemetry-schema` - [ ] Does user-controlled data reach NGINX config? → Verify sanitization path exists and is tested ## Definition of Done Do not report a task as complete until every applicable box is ticked. These are the steps most often skipped. | Condition | Required action | Verification | | --- | --- | --- | | Edited any `.tmpl` | Snapshot fixture added **and** regenerated | `git diff -- '**/__snapshots__/**'` is non-empty and shows the new directive | | Edited a template struct (`version1/config.go`, `version2/http.go`, `version2/stream.go`) | Fixture populates the field, snapshots regenerated | Same as above | | Edited `pkg/apis/**/types.go` | `make update-codegen && make update-crds` | `git status` shows regenerated `pkg/**`, `config/crd/bases`, `deploy/crds*.yaml`, `docs/crd/` | | Edited telemetry `Data` / `NICResourceCounts` | `make telemetry-schema` | No diff on re-run | | Added/changed imports | `go mod tidy` | `go.mod` / `go.sum` clean | | Edited chart templates or values | testdata + helmunit case | `charts/tests/__snapshots__/` diff is non-empty | | Added a pytest marker | Registered in `pyproject.toml` | Suite runs under `--strict-markers` | | Any of the above | `make test` then `make lint` | Both pass | **Snapshot rule:** regenerating without adding a fixture produces an empty diff, which is a *silent failure*, not a success. If `make test-update-snaps` changes nothing after a template edit, you have not tested the feature. ## Scope Assessment | Scope | Indicators | Action | | --- | --- | --- | | Trivial | Typo, docs, comment fix | Fix directly, no plan needed | | Small | Single layer, <50 lines, no API change | Brief plan → implement → test | | Medium | 2-3 layers, new field or annotation | Detailed plan → implement layer by layer → test each | | Large | New subsystem, new policy type, cross-cutting | Write plan document → get approval → implement in stages | ## Common Planning Mistakes - Starting implementation before understanding the full scope of affected files - Forgetting to update BOTH OSS and Plus templates for a shared directive -- or the inverse, leaking a Plus-only directive into the OSS template - Changing `types.go` without running codegen - Adding a VirtualServer feature without checking if Ingress (v1) also needs it - Adding Helm values without updating the JSON schema - Not checking if the feature already exists as an annotation when adding a CRD field - Skipping snapshot regeneration after template changes -- or regenerating without adding a fixture, which silently produces no diff - Forgetting `make telemetry-schema` after touching telemetry data types - Assuming a directive exists or behaves a certain way without checking <https://nginx.org/en/docs/> -- verify NGINX semantics before wiring a template - Not identifying where untrusted input enters — a new CRD field IS user input that reaches NGINX config - Skipping negative tests — only testing the happy path leaves injection vectors undiscovered ## Ordering Rules for Multi-Layer Changes When a change spans multiple layers, implement in this order: 1. **Data model** — Define types/fields in `types.go` 2. **Codegen** — `make update-codegen && make update-crds` 3. **Validation** — Add validation rules in `pkg/apis/configuration/validation/` 4. **Config structs** — Add fields to template structs in `version1/` or `version2/` 5. **Config generation** — Wire the new field into config builders in `internal/configs/` 6. **Templates** — Add NGINX directives to `.tmpl` files (OSS + Plus) 7. **Controller** — Wire into sync handlers if needed 8. **Helm** — Update chart values, schema, templates 9. **Tests** — Unit, negative, snapshot (fixture + regenerate), helm, integration 10. **Regenerate** — `make update-codegen`, `make update-crds`, `make telemetry-schema`, `make test-update-snaps`, then `make test` and `make lint`
More agent context in nginx/kubernetes-ingress
11 other files this repository gives its agents.
AGENTS.md
CLAUDE.md
Copilot instructions
Skill
- nic-add-feature.github/skills/nic-add-feature/SKILL.md
- nic-add-policy.github/skills/nic-add-policy/SKILL.md
- nic-ci-pipelines.github/skills/nic-ci-pipelines/SKILL.md
- nic-code-review.github/skills/nic-code-review/SKILL.md
- nic-debugging.github/skills/nic-debugging/SKILL.md
- nic-docker-images.github/skills/nic-docker-images/SKILL.md
- nic-structure.github/skills/nic-structure/SKILL.md
- nic-testing.github/skills/nic-testing/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
Reports can't be read right now.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool registry_write, action report. How to connect one.

