agentleFS
Microsoft AzureKnown publisherAzure/azure-verified-modules-managed-files/terraform/root/.github/skills/avm-tf-interfaces/SKILL.md

avm-tf-interfaces

Skill1 starsChanged 2 months agoMITView on GitHub

Use for AVM Terraform diagnostic settings, role assignments, locks, managed identities, private endpoints, customer-managed keys, tags, and AzAPI control interfaces.

232 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

9 rules. About 0 are common, 7 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈7

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Read the current RMFR4, RMFR5, TFFR6, TFFR7, TFFR8, and TFNFR38 pages through <https://azure.github.io/Azure-Verified-Modules/llms.txt>.

    line 8
  2. Distinctive:

    Treat the entire canonical variable declaration as atomic.

    line 19
  3. Distinctive:

    Only pass inputs supported by the resource.

    line 33
  4. Distinctive:

    Do not expose a no-op interface or rename a standard variable.

    line 49
  5. Distinctive:

    Do not use the utility module's legacy diagnostic-settings input or output in new code.

    line 87
  6. Very specific:

    Keep the primary resource label this.

    line 146
  7. Very specific:

    Use unquoted lifecycle references such as ignore_changes = [name].

    line 149
  8. Distinctive:

    Do not create destination workspaces, virtual networks, subnets, key vaults, or other consumer-owned dependencies inside a resource module.

    line 150
  9. Distinctive:

    Keep standard collection inputs non-null with empty defaults.

    line 151

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

AVM Terraform Interfaces

Read the current RMFR4, RMFR5, TFFR6, TFFR7, TFFR8, and TFNFR38 pages through https://azure.github.io/Azure-Verified-Modules/llms.txt.

Every new module MUST use AzAPI for its primary resource and every directly authored standard-interface or supporting control-plane Azure resource. Do not use AzureRM for convenience in implementation, examples, tests, fixtures, E2E setup, or generated snippets. Each permitted azurerm_* resource or data-source block must independently implement one specific unsupported data-plane/non-ARM operation, document the exact block and AzAPI gap with an upstream AzAPI issue or pull request, and be replaced when support ships. One valid block does not authorize another.

Canonical utility module

For every RMFR4 or RMFR5 interface migration, fetch both current sources from Azure/Azure-Verified-Modules:

  • https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/refs/heads/main/docs/content/specs-defs/specs/terraform/interfaces.md
  • the matching https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/refs/heads/main/docs/static/includes/interfaces/tf/int.<interface>.schema.tf

Treat the entire canonical variable declaration as atomic. Copy it in full and replace only documented placeholders; preserve attribute ordering, types, defaults, nullability, descriptions, validations, and error messages exactly. Lint notices are migration hints, not complete implementation instructions.

The resource module declares the exact consumer-facing schema. Azure/avm-utl-interfaces/azure provides the implementation and composition:

module "avm_interfaces" {
  source  = "Azure/avm-utl-interfaces/azure"
  version = "~> 0.6"

  diagnostic_settings_v2 = var.diagnostic_settings
  managed_identities     = var.managed_identities
}

Only pass inputs supported by the resource. Keep the utility version constraint current with the specification and Registry release.

Resource-feature interfaces

Expose an interface only when the Azure resource supports the capability:

InterfaceConsumer variablePurpose
Diagnostic settingsdiagnostic_settingsRoute logs and metrics to supported destinations.
Role assignmentsrole_assignmentsCreate RBAC assignments scoped to the resource.
LockslockApply an optional CanNotDelete or ReadOnly management lock.
Managed identitiesmanaged_identitiesConfigure system-assigned and user-assigned identities.
Private endpointsprivate_endpointsCreate private endpoints and optional DNS-zone integration.
Customer-managed keycustomer_managed_keyConfigure supported CMK encryption.
TagstagsApply tags to resources that support them.

Do not expose a no-op interface or rename a standard variable.

Diagnostic settings v2

New modules use:

  • utility input diagnostic_settings_v2; and
  • utility output diagnostic_settings_azapi_v2.

The v2 shape supports log category or category group, metrics, enabled flags, and retention policy objects. Do not restrict category values because Azure can add categories.

The owning module supplies scope and all TFFR4-TFFR8 controls:

resource "azapi_resource" "diagnostic_settings" {
  for_each = module.avm_interfaces.diagnostic_settings_azapi_v2

  type      = var.resource_types.insights_diagnostic_settings
  name      = each.value.name
  parent_id = azapi_resource.this.id
  body      = each.value.body

  ignore_body_changes    = length(var.ignore_body_changes.insights_diagnostic_settings) > 0 ? var.ignore_body_changes.insights_diagnostic_settings : null
  response_export_values = []
  retry                  = var.retry

  dynamic "timeouts" {
    for_each = var.timeouts == null ? [] : [var.timeouts]
    content {
      create = timeouts.value.create
      read   = timeouts.value.read
      update = timeouts.value.update
      delete = timeouts.value.delete
    }
  }
}

Do not use the utility module's legacy diagnostic-settings input or output in new code.

AzAPI control interfaces

These apply to every AzAPI resource, independently of optional resource features:

resource_types

The object contains one deterministic key per AzAPI resource and nested objects matching submodules. Each owning module defines its own tested API-version defaults. Parent slots do not repeat child string defaults.

retry and timeouts

Expose the TFFR7 object shapes. Apply both to every AzAPI resource and cascade them unchanged to every submodule:

retry = var.retry

dynamic "timeouts" {
  for_each = var.timeouts == null ? [] : [var.timeouts]
  content {
    create = timeouts.value.create
    read   = timeouts.value.read
    update = timeouts.value.update
    delete = timeouts.value.delete
  }
}

ignore_body_changes

Expose one optional(list(string), []) field per owned AzAPI resource and one nested child-shaped object per submodule. Apply the matching field and collapse an empty list to null:

ignore_body_changes = length(var.ignore_body_changes.example_widgets) > 0 ? var.ignore_body_changes.example_widgets : null

Pass only the matching nested slot to a child. Do not cascade the parent's path list unchanged because paths are specific to one resource body.

Paths use body-relative dot notation. Individual list indices cannot be targeted. Ignored configuration is not sent to Azure until the path is removed, and interface changes take effect only after apply.

Resource ID validation

Validate standard interface resource IDs with TFNFR38 where each field has one expected resource type:

validation {
  condition = alltrue([
    for endpoint in values(var.private_endpoints) :
    can(provider::azapi::parse_resource_id("Microsoft.Network/virtualNetworks/subnets", endpoint.subnet_resource_id))
  ])
  error_message = "Each subnet_resource_id must be a valid subnet resource ID."
}

Handle nullable values and collections explicitly. If a field legitimately accepts unrelated resource types, do not validate it against one arbitrary type.

Composition rules

  • Implement locks, role assignments, diagnostic settings, private endpoints, and other child or extension resources as distinct, descriptively named resources or required submodules.
  • Keep the primary resource label this.
  • Source every AzAPI type from var.resource_types.
  • Apply response_export_values, retry, timeouts, and ignore_body_changes to every applicable AzAPI resource. Omit replace_triggers_refs when no replacement paths exist; otherwise use a non-empty static list of unique, valid JMESPath body paths.
  • Use unquoted lifecycle references such as ignore_changes = [name].
  • Do not create destination workspaces, virtual networks, subnets, key vaults, or other consumer-owned dependencies inside a resource module.
  • Keep standard collection inputs non-null with empty defaults.

Consult the canonical schema files for exact consumer-facing declarations and the Azure/avm-utl-interfaces/azure release documentation for implementation inputs and outputs. Do not reconstruct either from memory.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.