| 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
- Read the requirement — Understand what's being asked. Check linked issues, specs, or PRs for full context.
- Write acceptance criteria — Before implementing, state what "done" looks like in testable terms. What should work? What should be rejected? What must NOT break?
- 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
- 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/)
- 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: Always update BOTH OSS and Plus variants
- CRD fields: Every new field needs kubebuilder markers + validation + template + tests
- 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
- 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:
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
- 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
- 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:
- Data model — Define types/fields in
types.go
- Codegen —
make update-codegen && make update-crds
- Validation — Add validation rules in
pkg/apis/configuration/validation/
- Config structs — Add fields to template structs in
version1/ or version2/
- Config generation — Wire the new field into config builders in
internal/configs/
- Templates — Add NGINX directives to
.tmpl files (OSS + Plus)
- Controller — Wire into sync handlers if needed
- Helm — Update chart values, schema, templates
- Tests — Unit, snapshot, helm, integration