Use when designing the structure, CI/CD, state organization, testing strategy, security pipeline, or operational pattern of a Terraform repository that uses any Zscaler provider (zpa, zia, ztc, zcc). Cross-cutting engineering discipline that complements the per-product zpa-skill / zia-skill / ztc-skill / zcc-skill — covers state backends and per-tenant / per-microtenant blast-radius decisions, CI/CD pipelines that include the Zscaler activation step, OIDC against Zidentity, secret handling (write_only on 1.11+, no credentials in tfvars/state), Trivy/Checkov for HCL scanning, native terraform test against sandbox tenants, mock providers, module composition, naming, versioning, anti-patterns, and a DO/DON'T quick reference.
How this skill is triggered — by the user, by Claude, or both
Slash command
/zscaler-terraform-skills:best-practices-skillThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Diagnose-first guidance for **how to structure, ship, and operate** Terraform repositories that consume the Zscaler providers. This skill is **provider-agnostic across the four Zscaler products** — for resource-level catalog, auth, and lifecycle quirks of a specific provider, route to `zpa-skill` / `zia-skill` / `ztc-skill` / `zcc-skill`.
references/anti-patterns.mdreferences/ci-cd-zscaler.mdreferences/coding-practices.mdreferences/module-patterns.mdreferences/naming-conventions.mdreferences/quick-reference.mdreferences/security-and-compliance.mdreferences/state-management.mdreferences/testing-and-validation.mdreferences/variables-and-outputs.mdreferences/versioning.mdDiagnose-first guidance for how to structure, ship, and operate Terraform repositories that consume the Zscaler providers. This skill is provider-agnostic across the four Zscaler products — for resource-level catalog, auth, and lifecycle quirks of a specific provider, route to zpa-skill / zia-skill / ztc-skill / zcc-skill.
Scope: state organization, CI/CD shape, secret handling, testing strategy, module patterns, naming, versioning, anti-patterns. Things that don't belong in any single provider skill because they apply to all of them — and are different enough from generic Terraform to need Zscaler-specific guidance.
Every best-practices response must include:
fmt -check, validate, plan -out, trivy config, checkov, terraform test).Never recommend terraform state rm against any Zscaler resource (orphans the API object — see provider skills' troubleshooting).
| Field | Why it matters | Default if missing |
|---|---|---|
| Providers in scope | Which of zpa / zia / ztc / zcc does this repo or change touch? | Ask. Don't assume single-provider. |
| Tenants & microtenants | One tenant or many? Microtenants? Same Zidentity org or separate? Drives state-org and CI fan-out. | Ask. Don't assume single-tenant. |
| Auth path | OneAPI (Zidentity) vs Legacy v3. CI secret model differs (OneAPI client creds vs legacy username/password/api_key). | Ask. Don't default — see provider skill auth refs. |
| Execution path | Local / GitHub Actions / GitLab CI / Atlantis / Terraform Cloud / Spacelift. | Ask. |
| Environment criticality | Sandbox / non-prod / prod. Drives approval model, plan-artifact requirement, activation gating. | Treat as prod unless told otherwise. |
| Activation discipline | Is <product>_activation_status (ZIA / ZTC) included in the same state, separate stage, or done manually? | Ask. Strongly recommend in-state for ZIA/ZTC. |
| Terraform runtime version | Affects optional(), moved, import, removed, write_only, mock providers, use_lockfile. | Assume terraform ~> 1.9. |
| Discipline gap | Symptoms | Primary references |
|---|---|---|
| State organization / blast radius | One state file for all Zscaler resources, microtenant teams blocked on each other's plans, locks held for hours | State Management |
| CI/CD shape | "How do I PR-test policy changes?", forgot activation step in CI, secrets baked into pipeline YAML, plan re-run in apply job | CI/CD |
| Activation forgotten in CI | Apply succeeds but ZIA/ZTC console shows no change, <product>_activation_status missing from CI flow | CI/CD: Activation Step |
| Secret exposure / compliance | client_secret in .tfvars, in state, in CI logs; long-lived credentials instead of OIDC | Security & Compliance |
| Testing strategy | "How do I validate before merge?", no sandbox tenant, mock vs real provider confusion, computed-value assertions failing | Testing & Validation |
| Module structure / boundaries | "One module or three?", mixing ZPA + ZIA in one module, kitchen-sink god module, lifecycle confusion | Module Patterns |
| Coding shape (loops, locals, dynamic) | count over a list shifting addresses, hardcoded IDs, dynamic block where static would do, validation gaps | Coding Practices |
| Naming, layout, drift | Inconsistent resource names, file-organization confusion, "this" everywhere, opaque variable names | Naming Conventions |
| Variables and outputs | Weak typing (any), parallel lists, missing validation, exposing entire resources | Variables and Outputs |
| Versioning / lockfile / upgrades | Provider upgrade broke prod, no lockfile committed, exact pin blocks fixes, init -upgrade in feature PR | Versioning |
| Anti-patterns / "is this OK?" | Recurring footguns: state rm, provider {} in modules, manual activation, mixed env vars | Anti-Patterns |
| Quick lookup / DO-DON'T | Cheat-sheet question, naming question, "is X allowed?" | Quick Reference |
These apply to every Zscaler-Terraform repo regardless of which provider you use. Detailed playbooks live in the references; this section is the fast-path.
client_secret, password, api_key, private_key in .tfvars checked into git.client_secret in a Terraform variable on Terraform < 1.11 (it ends up in state, even with sensitive = true).ZSCALER_CLIENT_SECRET, ZSCALER_PRIVATE_KEY, ZIA_API_KEY, etc.).1.11+, use write_only arguments (*_wo) to keep credentials out of state entirely.terraform state rm a Zscaler resourceThe API object stays orphaned. Use terraform apply -target= (selective destroy) or removed blocks (Terraform 1.7+) instead. See each provider skill's troubleshooting for product-specific recovery.
<product>_activation_status in the same state.zia_activation_status / ztc_activation_status as a depends_on resource at the bottom of the same state.See CI/CD: Activation as a Pipeline Stage.
See State Management.
for_each over count for any list of named Zscaler objectscount over a list reshuffles every address when an item is removed from the middle — meaning a single removed app segment can churn every downstream zpa_application_segment resource. Use for_each = toset(...) or for_each = map. The only safe count is the boolean count = condition ? 1 : 0 toggle for an optional resource.
required_version = "~> 1.9" (or your floor).version = "~> 4.0" for zscaler/zpa, zscaler/zia, zscaler/ztc; version = "~> 0.1" for the not-yet-1.0 zscaler/zcc..terraform.lock.hcl. Updates are a separate PR from feature work.fmt -check, validate, tflint) on every PR — free, instant.terraform plan against a non-prod tenant on every PR.terraform test (Terraform 1.6+) for input-validation coverage.See Testing & Validation.
| Type | When to use | Zscaler example |
|---|---|---|
| Resource module | Single logical Zscaler-API grouping created together | ZPA segment_group + server_group + application_segment for one app |
| Infrastructure module | Collection of resource modules for one tenant / one product | "All ZPA app segments for prod tenant", "All ZIA URL filtering rules for prod tenant" |
| Composition (root) | Per-environment top-level config that wires infrastructure modules | environments/prod/zpa/, environments/prod/zia/ |
❌ Do not mix zia_* and zpa_* resources in the same module — different lifecycles, different activation rules, different tenants likely.
✅ Modules are reusable; root configs are not. Reusable modules never declare provider blocks — the root composes them.
Detailed patterns: Module Patterns.
Progressive disclosure — essentials in this skill router, depth on demand.
Operational discipline:
state rm rationale, multi-team isolation, cross-state references.write_only / ephemeral on 1.11+), Trivy/Checkov/tflint, custom OPA policies, audit-trail pattern, SOC2 / ISO 27001 / PCI / FedRAMP mappings.terraform test (1.6+), mock_provider (1.7+) limits, sandbox-tenant integration with cleanup, acceptance-criteria-by-risk-tier table.Code shape:
count vs for_each vs dynamic, locals, validation, dependency management, provider-block hygiene.optional(), validation blocks, sensitive handling, output design, Zscaler-flavored variable templates.Process discipline:
moved {}, OneAPI migration.Fast lookup:
Provider-specific guidance lives in the per-product skills. When the answer needs a resource attribute or auth field, route there:
zpa-skill — Zscaler Private Access resource catalog, OneAPI / legacy / GOV / microtenant auth, policy rule semantics.zia-skill — Zscaler Internet Access resource catalog, rule ordering, activation lifecycle.ztc-skill — Zscaler Zero Trust Cloud resource catalog, cloud-orchestrated objects, activation lifecycle.zcc-skill — Zscaler Client Connector resource catalog, singleton / existing-only patterns.Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub zscaler/zscaler-terraform-skills --plugin zscaler-terraform-skills