Why Abandoned Resources Are a Security Problem, Not Just a Billing One

Why Abandoned Resources Are a Security Problem, Not Just a Billing One
Everything here is built on the work of Dolev Shor. His Azure Orphaned Resources workbook has 745 GitHub stars and is genuinely one of the most useful things anyone has built for Azure operators. I piggybacked on his foundation, added what I needed, and adapted it for my own environments. He did the hard work. I just customised the result. Go star his repo.

All right class.

You have got Azure. You have spent time and money building it. And then somewhere along the way, someone forgot to clean up after themselves.

An unattached managed disk sitting in a resource group nobody owns. A public IP address that has not been associated with anything in six months. A VPN Gateway spinning away at £138 a month with zero connections. An App Service Plan with no apps hosted on it. An empty DDoS Protection Plan burning through £2,944 a month because someone decommissioned the workload and left the plan running.

Nobody reports this. Nobody notices this. It just sits there costing money and expanding your attack surface at the same time.


This Is Not Just a Billing Problem

An unattached managed disk still contains data. Whatever was on that VM when it was decommissioned is still sitting on that disk, readable by anyone with the right permissions on the resource group. A public IP with no associated resource can be reassigned. A disconnected private endpoint means traffic routing is not what you think it is. A storage account nobody uses anymore might be holding Terraform state, diagnostic logs, or backup metadata that you absolutely do not want deleted or exposed.

Orphaned resources are forgotten attack surface (and governance risk). The cost is the symptom. The risk is the actual problem.

What This Workbook Covers

The workbook queries Azure Resource Graph across whichever subscriptions and resource groups you select. It is split into tabs covering Compute, Storage, Networking, Database, and an Others section that catches the stuff that does not fit neatly elsewhere.

What each tab surfaces:

  • Compute: App Service Plans with zero apps hosted, Availability Sets not attached to any VM or VMSS
  • Storage: Unattached managed disks (with ASR replicas and Kubernetes PVC disks excluded), Storage accounts older than 90 days flagged for review
  • Networking: Orphaned public IPs, empty load balancers, NAT Gateways with no subnets, Private DNS Zones with no VNet links, disconnected Private Endpoints, VNet Gateways with no connections, Application Gateways with empty backend pools, Traffic Manager profiles with no endpoints, DDoS Protection Plans with no associated VNets
  • Database: SQL Elastic Pools with zero databases
  • Others: Empty resource groups, abandoned Logic Apps, expired App Service certificates, stale API connections

What I Added on Top of the Original

UK South pricing on the cost tab. Every resource type that costs money has a monthly waste estimate built into the query using current UK South pricing. An idle Standard Load Balancer is $18 a month. An empty VPN Gateway running VpnGw1 is $138.70. An unused DDoS Network Protection Plan is $2,944. When you put a number in front of someone, they act. When you hand them a list of resource names, they file it and forget it.

The storage account tab is a review list, not a delete list. This is important. Accounts older than 90 days appear, but the workbook explicitly warns you to check StorageBlobLogsStorageFileLogsStorageQueueLogs, and StorageTableLogs before touching anything. An empty storage account can still be holding infrastructure state or diagnostic data. Age is not proof of abandonment.

Abandoned Logic Apps via AzureDiagnostics. Logic Apps that have not run in 30 days show up separately. This section needs a Log Analytics workspace in scope. If you see no data there, check your workspace parameter first before assuming you have no abandoned Logic Apps.

App Gateway V1 retirement flagged in the pricing basis column. The V1 WAF and Standard tiers for Application Gateway were retired in April 2026. If you have any of those showing up, the pricing column notes they are retired so you are not confused about cost estimates for something that should have been migrated already.


The Deletion Button

The workbook has a deletion feature. It is off by default, which is correct.

To enable it, toggle the Enable Deletion parameter in the filter pane at the top. Once enabled, each resource type section gets a Delete Selected Resource button. You select the row, click delete, confirm in the context blade, and the workbook fires a DELETE request against the ARM API.

You need Contributor on the resource group for this to work. Without it, the action will fail silently or give you a generic permission error.

One thing nobody tells you: the API versions in the workbook are hardcoded per resource type. They were accurate at time of writing. If a delete action fails with a 400 or 404 unexpectedly, check whether Microsoft has deprecated that API version for that resource type and update the api-version parameter in the relevant link action in the JSON.

Delete resources one at a time where you can. The ARM API does not always like bulk deletion but in most of the cases it should work just fine.


How to Deploy It

Step 1: Open the Azure Portal and navigate to Azure Workbooks under Microsoft Sentinel (or Azure Monitor)
Step 2: Click New.
Step 3: Click the Advanced Editor button (the code icon on the toolbar).
Step 4: Make sure the type is set to Gallery Template.
Step 5: Delete everything in the editor and paste in the full workbook JSON below.
Step 6: Click Apply, then Save. Give it a name, pick a subscription and resource group to save it in.
Step 7: Open the workbook. Set your subscription and resource group parameters in the filter pane. Work through the tabs.

Start with the cost tab to understand the financial scale of what you are looking at. Then move tab by tab. Do not use the deletion feature on your first run. Review everything first.

The full JSON is below.

{
  "version": "Notebook/1.0",
  "items": [
    {
      "type": 1,
      "content": {
        "json": "# Forsaken Resources\nVisibility into wasted Azure infrastructure. Every resource here is confirmed forsaken.\n\n💲 marks resource types that cost money even when unused.\n\n---\n*Built by [itprofessor.cloud](https://itprofessor.cloud)*"
      },
      "name": "hdr"
    },
    {
      "type": 9,
      "content": {
        "version": "KqlParameterItem/1.0",
        "crossComponentResources": [
          "{Subscription}"
        ],
        "parameters": [
          {
            "id": "p1",
            "version": "KqlParameterItem/1.0",
            "name": "Subscription",
            "type": 6,
            "isRequired": true,
            "multiSelect": true,
            "quote": "'",
            "delimiter": ",",
            "typeSettings": {
              "additionalResourceOptions": [
                "value::all"
              ],
              "includeAll": true,
              "showDefault": false
            },
            "value": []
          },
          {
            "id": "p2",
            "version": "KqlParameterItem/1.0",
            "name": "ResourceGroup",
            "label": "Resource Group",
            "type": 5,
            "isRequired": true,
            "multiSelect": true,
            "quote": "'",
            "delimiter": ",",
            "query": "ResourceContainers\n| where type =~ 'microsoft.resources/subscriptions/resourcegroups'\n| distinct resourceGroup",
            "crossComponentResources": [
              "{Subscription}"
            ],
            "typeSettings": {
              "additionalResourceOptions": [
                "value::all"
              ],
              "showDefault": false
            },
            "queryType": 1,
            "value": []
          },
          {
            "id": "p3",
            "version": "KqlParameterItem/1.0",
            "name": "EnableDeletion",
            "label": "Enable Deletion",
            "type": 2,
            "isRequired": true,
            "query": "{\"version\":\"1.0.0\",\"content\":\"[{\\\"value\\\": \\\"false\\\", \\\"label\\\": \\\"Disabled (Recommended for prod testing first)\\\", \\\"selected\\\":true},{\\\"value\\\": \\\"true\\\", \\\"label\\\": \\\"⚠️ Enable (Irreversible - Requires Contributor)\\\"}]\",\"transformers\":null}",
            "typeSettings": {
              "additionalResourceOptions": [],
              "showDefault": false
            },
            "queryType": 8
          }
        ],
        "style": "pills",
        "queryType": 1,
        "resourceType": "microsoft.resourcegraph/resources"
      },
      "name": "params"
    },
    {
      "type": 11,
      "content": {
        "version": "LinkItem/1.0",
        "style": "tabs",
        "links": [
          {
            "id": "t1",
            "cellValue": "mainTab",
            "linkTarget": "parameter",
            "linkLabel": "Overview",
            "subTarget": "overview",
            "style": "link"
          },
          {
            "id": "t2",
            "cellValue": "mainTab",
            "linkTarget": "parameter",
            "linkLabel": "Forsaken Age",
            "subTarget": "age",
            "style": "link"
          },
          {
            "id": "t3",
            "cellValue": "mainTab",
            "linkTarget": "parameter",
            "linkLabel": "Cost Impact",
            "subTarget": "cost",
            "style": "link"
          },
          {
            "id": "t4",
            "cellValue": "mainTab",
            "linkTarget": "parameter",
            "linkLabel": "Compute",
            "subTarget": "compute",
            "style": "link"
          },
          {
            "id": "t5",
            "cellValue": "mainTab",
            "linkTarget": "parameter",
            "linkLabel": "Storage",
            "subTarget": "storage",
            "style": "link"
          },
          {
            "id": "t6",
            "cellValue": "mainTab",
            "linkTarget": "parameter",
            "linkLabel": "Database",
            "subTarget": "database",
            "style": "link"
          },
          {
            "id": "t7",
            "cellValue": "mainTab",
            "linkTarget": "parameter",
            "linkLabel": "Networking",
            "subTarget": "networking",
            "style": "link"
          },
          {
            "id": "t8",
            "cellValue": "mainTab",
            "linkTarget": "parameter",
            "linkLabel": "Abandoned Resources",
            "subTarget": "abandoned",
            "style": "link"
          }
        ]
      },
      "name": "maintabs"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "### Forsaken Resources | itprofessor.cloud\n\nEach tile shows confirmed forsaken count. Resources only appear here when they have no active association.\n\n💲 marks resource types that generate charges when forsaken.",
              "style": "upsell"
            },
            "name": "ov_banner"
          },
          {
            "type": 1,
            "content": {
              "json": "💲 This sign indicates the resource costs money even when forsaken.",
              "style": "info"
            },
            "name": "ov_costinfo"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.web/serverfarms'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.numberOfSites == 0\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.web/serverfarms\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov1"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/availabilitysets'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.virtualMachines == \"[]\"\n| where not(name endswith '-asr')\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.compute/availabilitysets\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": " ",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov2"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/disks'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend diskState = tostring(properties.diskState)\n| where (managedBy == \"\" and diskState != 'ActiveSAS') or (diskState == 'Unattached' and diskState != 'ActiveSAS')\n| where not(name endswith \"-ASRReplica\" or name startswith \"ms-asr-\" or name startswith \"asrseeddisk-\")\n| where (tags !contains \"kubernetes.io-created-for-pvc\") and tags !contains \"ASR-ReplicaDisk\" and tags !contains \"asrseeddisk\" and tags !contains \"RSVaultBackup\"\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.compute/disks\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov3"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.sql/servers/elasticpools'\n| where resourceGroup in~ ({ResourceGroup:value})\n| project elasticPoolId = tolower(id), Resource = id, type\n| join kind=leftouter (resources\n| where type =~ 'microsoft.sql/servers/databases'\n| project id, properties\n| extend elasticPoolId = tolower(properties.elasticPoolId)) on elasticPoolId\n| summarize databaseCount = countif(id != '') by Resource, type\n| where databaseCount == 0\n| project-away databaseCount\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.sql/servers/elasticpools\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov4"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.network/publicipaddresses'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.ipConfiguration == \"\" and properties.natGateway == \"\" and properties.publicIPPrefix == \"\"\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/publicipaddresses\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov5"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.network/networkinterfaces'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where isnull(properties.privateEndpoint)\n| where isnull(properties.privateLinkService)\n| where properties.hostedWorkloads == \"[]\"\n| where properties !has 'virtualmachine'\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/networkinterfaces\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": " ",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov6"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.network/networksecuritygroups' and isnull(properties.networkInterfaces) and isnull(properties.subnets)\n| where resourceGroup in~ ({ResourceGroup:value})\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/networksecuritygroups\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": " ",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov7"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/routetables'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where isnull(properties.subnets)\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/routetables\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": " ",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov8"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/loadbalancers'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.backendAddressPools == \"[]\" and properties.inboundNatRules == \"[]\" and properties.outboundRules == \"[]\"\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/loadbalancers\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov9"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/frontdoorwebapplicationfirewallpolicies'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.securityPolicyLinks== \"[]\"\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/frontdoorwebapplicationfirewallpolicies\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": " ",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov10"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/trafficmanagerprofiles'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.endpoints == \"[]\"\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/trafficmanagerprofiles\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": " ",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov11"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/applicationgateways'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend AppGwId = tostring(id)\n| join (\n    resources\n    | where type =~ 'microsoft.network/applicationgateways'\n    | mvexpand backendPools = properties.backendAddressPools\n    | extend backendIPCount = array_length(backendPools.properties.backendIPConfigurations)\n    | extend backendAddressesCount = array_length(backendPools.properties.backendAddresses)\n    | extend AppGwId = tostring(id)\n    | summarize backendIPCount = sum(backendIPCount), backendAddressesCount = sum(backendAddressesCount) by AppGwId\n) on AppGwId\n| where (backendIPCount == 0 or isempty(backendIPCount)) and (backendAddressesCount == 0 or isempty(backendAddressesCount))\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/applicationgateways\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov12"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/virtualnetworks'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.subnets == \"[]\"\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/virtualnetworks\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": " ",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov13"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/natgateways'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where isnull(properties.subnets)\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/natgateways\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov14"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/ipgroups'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.firewalls == \"[]\" and properties.firewallPolicies == \"[]\"\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/ipgroups\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": " ",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov15"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/privatednszones'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.numberOfVirtualNetworkLinks == 0\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/privatednszones\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov16"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/privateendpoints'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend connection = iff(array_length(properties.manualPrivateLinkServiceConnections) > 0, properties.manualPrivateLinkServiceConnections[0], properties.privateLinkServiceConnections[0])\n| extend stateEnum = tostring(connection.properties.privateLinkServiceConnectionState.status)\n| where stateEnum == 'Disconnected'\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/privateendpoints\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov17"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/virtualnetworkgateways'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend vpnClientConfiguration = properties.vpnClientConfiguration\n| extend Resource = id\n| join kind=leftouter (\n  resources\n  | where type =~ 'microsoft.network/connections'\n  | mv-expand Resource = pack_array(properties.virtualNetworkGateway1.id, properties.virtualNetworkGateway2.id) to typeof(string)\n  | project Resource, connectionId = id, ConnectionProperties=properties\n ) on Resource\n| where isempty(vpnClientConfiguration) and isempty(connectionId)\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/virtualnetworkgateways\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov18"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/ddosprotectionplans'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where isnull(properties.virtualNetworks)\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/ddosprotectionplans\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": "💲",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov19"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ResourceContainers\n| where type =~ 'microsoft.resources/subscriptions/resourcegroups'\n| extend rgAndSub = strcat(resourceGroup, \"--\", subscriptionId)\n| join kind=leftouter (Resources | extend rgAndSub = strcat(resourceGroup, \"--\", subscriptionId) | summarize count() by rgAndSub) on rgAndSub\n| where isnull(count_)\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.resources/subscriptions/resourcegroups\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": " ",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov20"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "AzureDiagnostics\n| where ResourceProvider == \"MICROSOFT.LOGIC\"\n| where OperationName == \"Microsoft.Logic/workflows/workflowRunCompleted\"\n| where TimeGenerated > ago(730d)\n| where resource_resourceGroupName_s in~ ({ResourceGroup:value})\n| extend workflowName = tostring(resource_workflowName_s)\n| summarize LastRun = max(TimeGenerated) by workflowName\n| where LastRun < ago(30d)\n| summarize count_ = count()\n| extend type = \"Logic Apps\", total_count = count_\n| project type, total_count",
                    "size": 3,
                    "title": " ",
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov21"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.web/certificates'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend expiresOn = todatetime(properties.expirationDate)\n| where expiresOn <= now()\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.web/certificates\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 3,
                    "title": " ",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "16.5",
                  "name": "ov22"
                }
              ]
            },
            "name": "grp_ov_tiles"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "mainTab",
        "comparison": "isEqualTo",
        "value": "overview"
      },
      "name": "grp_overview"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "## Forsaken Resource Age\n\nEvery resource shown here is confirmed forsaken using the exact same detection logic as the Overview tiles. Sorted by age descending so the longest-sitting resources are at the top.\n\n💲 marks resource types that continue to generate charges even when forsaken."
            },
            "name": "age_info"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Resources\n| where resourceGroup in~ ({ResourceGroup:value})\n| where type in~ ('microsoft.web/serverfarms', 'microsoft.compute/availabilitysets', 'microsoft.compute/disks', 'microsoft.network/publicipaddresses', 'microsoft.network/networkinterfaces')\n| where (type == 'microsoft.web/serverfarms' and properties.numberOfSites == 0)\n   or (type == 'microsoft.compute/availabilitysets' and properties.virtualMachines == '[]' and name !endswith '-asr')\n   or (type == 'microsoft.compute/disks' and ((managedBy == '' and tostring(properties.diskState) != 'ActiveSAS') or (tostring(properties.diskState) == 'Unattached' and tostring(properties.diskState) != 'ActiveSAS')) and name !endswith '-ASRReplica' and name !startswith 'ms-asr-' and name !startswith 'asrseeddisk-' and tags !contains 'kubernetes.io-created-for-pvc' and tags !contains 'ASR-ReplicaDisk' and tags !contains 'asrseeddisk' and tags !contains 'RSVaultBackup')\n   or (type == 'microsoft.network/publicipaddresses' and properties.ipConfiguration == '' and properties.natGateway == '' and properties.publicIPPrefix == '')\n   or (type == 'microsoft.network/networkinterfaces' and isnull(properties.privateEndpoint) and isnull(properties.privateLinkService) and properties.hostedWorkloads == '[]' and properties !has 'virtualmachine')\n| extend createdTime = todatetime(properties.timeCreated)\n| extend ['Age (Days)'] = iff(isnull(createdTime), int(null), datetime_diff('day', now(), createdTime))\n| extend ['Age Category'] = case(isnull(['Age (Days)']), '🔍 Needs Manual Review (no timeCreated)', ['Age (Days)'] > 90, '🔴 Over 90 days', ['Age (Days)'] > 30, '🟠 30 to 90 days', '🟡 Under 30 days')\n| project ['Resource Name']=name, ['Resource Type']=type, ['Resource Group']=resourceGroup, Location=location, ['Age (Days)'], ['Age Category'], subscriptionId, ['Resource ID']=id\n| order by ['Age (Days)'] desc",
              "size": 3,
              "title": "App Service Plans | Availability Sets | Disks | Public IPs | NICs",
              "noDataMessage": "No forsaken resources found for these types.",
              "exportMultipleValues": true,
              "exportedParameters": [
                {
                  "fieldName": "Resource ID",
                  "parameterName": "resources",
                  "parameterType": 5
                }
              ],
              "showExportToExcel": true,
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "table",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Resource Name",
                    "formatter": 13,
                    "formatOptions": {
                      "linkColumn": "Resource ID",
                      "linkTarget": "Resource",
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "Resource Type",
                    "formatter": 16,
                    "formatOptions": {
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "Resource Group",
                    "formatter": 14,
                    "formatOptions": {
                      "linkTarget": "Resource"
                    }
                  },
                  {
                    "columnMatch": "Location",
                    "formatter": 17
                  },
                  {
                    "columnMatch": "Age (Days)",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "redBright",
                      "min": 0,
                      "max": 730
                    }
                  },
                  {
                    "columnMatch": "Age Category",
                    "formatter": 1
                  },
                  {
                    "columnMatch": "subscriptionId",
                    "formatter": 5
                  },
                  {
                    "columnMatch": "Resource ID",
                    "formatter": 5
                  }
                ],
                "rowLimit": 1000,
                "filter": true
              },
              "sortBy": []
            },
            "name": "tbl_age_a"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Resources\n| where resourceGroup in~ ({ResourceGroup:value})\n| where type in~ ('microsoft.network/networksecuritygroups', 'microsoft.network/routetables', 'microsoft.network/loadbalancers', 'microsoft.network/natgateways', 'microsoft.network/privatednszones')\n| where (type == 'microsoft.network/networksecuritygroups' and isnull(properties.networkInterfaces) and isnull(properties.subnets))\n   or (type == 'microsoft.network/routetables' and isnull(properties.subnets))\n   or (type == 'microsoft.network/loadbalancers' and properties.backendAddressPools == '[]' and properties.inboundNatRules == '[]' and properties.outboundRules == '[]')\n   or (type == 'microsoft.network/natgateways' and isnull(properties.subnets))\n   or (type == 'microsoft.network/privatednszones' and properties.numberOfVirtualNetworkLinks == 0)\n| extend createdTime = todatetime(properties.timeCreated)\n| extend ['Age (Days)'] = iff(isnull(createdTime), int(null), datetime_diff('day', now(), createdTime))\n| extend ['Age Category'] = case(isnull(['Age (Days)']), '🔍 Needs Manual Review (no timeCreated)', ['Age (Days)'] > 90, '🔴 Over 90 days', ['Age (Days)'] > 30, '🟠 30 to 90 days', '🟡 Under 30 days')\n| project ['Resource Name']=name, ['Resource Type']=type, ['Resource Group']=resourceGroup, Location=location, ['Age (Days)'], ['Age Category'], subscriptionId, ['Resource ID']=id\n| order by ['Age (Days)'] desc",
              "size": 3,
              "title": "NSGs | Route Tables | Load Balancers | NAT Gateways | Private DNS Zones",
              "noDataMessage": "No forsaken resources found for these types.",
              "exportMultipleValues": true,
              "exportedParameters": [
                {
                  "fieldName": "Resource ID",
                  "parameterName": "resources",
                  "parameterType": 5
                }
              ],
              "showExportToExcel": true,
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "table",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Resource Name",
                    "formatter": 13,
                    "formatOptions": {
                      "linkColumn": "Resource ID",
                      "linkTarget": "Resource",
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "Resource Type",
                    "formatter": 16,
                    "formatOptions": {
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "Resource Group",
                    "formatter": 14,
                    "formatOptions": {
                      "linkTarget": "Resource"
                    }
                  },
                  {
                    "columnMatch": "Location",
                    "formatter": 17
                  },
                  {
                    "columnMatch": "Age (Days)",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "redBright",
                      "min": 0,
                      "max": 730
                    }
                  },
                  {
                    "columnMatch": "Age Category",
                    "formatter": 1
                  },
                  {
                    "columnMatch": "subscriptionId",
                    "formatter": 5
                  },
                  {
                    "columnMatch": "Resource ID",
                    "formatter": 5
                  }
                ],
                "rowLimit": 1000,
                "filter": true
              },
              "sortBy": []
            },
            "name": "tbl_age_b"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where resourceGroup in~ ({ResourceGroup:value})\n| where type in~ ('microsoft.network/virtualnetworks', 'microsoft.network/virtualnetworkgateways', 'microsoft.network/ipgroups', 'microsoft.network/trafficmanagerprofiles', 'microsoft.network/ddosprotectionplans')\n| where (type == 'microsoft.network/virtualnetworks' and properties.subnets == '[]')\n   or (type == 'microsoft.network/virtualnetworkgateways' and (isempty(properties.vpnClientConfiguration) and (array_length(properties.connections) == 0 or isnull(properties.connections))))\n   or (type == 'microsoft.network/ipgroups' and properties.firewalls == '[]' and properties.firewallPolicies == '[]')\n   or (type == 'microsoft.network/trafficmanagerprofiles' and properties.endpoints == '[]')\n   or (type == 'microsoft.network/ddosprotectionplans' and isnull(properties.virtualNetworks))\n| extend createdTime = todatetime(properties.timeCreated)\n| extend ['Age (Days)'] = iff(isnull(createdTime), int(null), datetime_diff('day', now(), createdTime))\n| extend ['Age Category'] = case(isnull(['Age (Days)']), '🔍 Needs Manual Review (no timeCreated)', ['Age (Days)'] > 90, '🔴 Over 90 days', ['Age (Days)'] > 30, '🟠 30 to 90 days', '🟡 Under 30 days')\n| project ['Resource Name']=name, ['Resource Type']=type, ['Resource Group']=resourceGroup, Location=location, ['Age (Days)'], ['Age Category'], subscriptionId, ['Resource ID']=id\n| order by ['Age (Days)'] desc",
              "size": 3,
              "title": "VNets | VNet Gateways | IP Groups | Traffic Manager | DDoS Plans",
              "noDataMessage": "No forsaken resources found for these types.",
              "exportMultipleValues": true,
              "exportedParameters": [
                {
                  "fieldName": "Resource ID",
                  "parameterName": "resources",
                  "parameterType": 5
                }
              ],
              "showExportToExcel": true,
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "table",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Resource Name",
                    "formatter": 13,
                    "formatOptions": {
                      "linkColumn": "Resource ID",
                      "linkTarget": "Resource",
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "Resource Type",
                    "formatter": 16,
                    "formatOptions": {
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "Resource Group",
                    "formatter": 14,
                    "formatOptions": {
                      "linkTarget": "Resource"
                    }
                  },
                  {
                    "columnMatch": "Location",
                    "formatter": 17
                  },
                  {
                    "columnMatch": "Age (Days)",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "redBright",
                      "min": 0,
                      "max": 730
                    }
                  },
                  {
                    "columnMatch": "Age Category",
                    "formatter": 1
                  },
                  {
                    "columnMatch": "subscriptionId",
                    "formatter": 5
                  },
                  {
                    "columnMatch": "Resource ID",
                    "formatter": 5
                  }
                ],
                "rowLimit": 1000,
                "filter": true,
                "sortBy": [
                  {
                    "itemKey": "Age (Days)",
                    "sortOrder": 2
                  }
                ]
              },
              "sortBy": [
                {
                  "itemKey": "Age (Days)",
                  "sortOrder": 2
                }
              ]
            },
            "name": "tbl_age_c"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "mainTab",
        "comparison": "isEqualTo",
        "value": "age"
      },
      "name": "grp_age"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "## Estimated Monthly Cost Impact\n\nShows only resource types that carry a direct charge when unused. Monthly waste is calculated by multiplying the forsaken count by the unit cost.\n\nPrices reflect actual Azure pay-as-you-go rates per SKU (UK South). Resources with unrecognised SKUs fall back to the nearest common tier estimate."
            },
            "name": "cost_info"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where type =~ 'microsoft.web/serverfarms'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.numberOfSites == 0\n| extend skuName = tostring(sku.name)\n| extend skuTier = tostring(sku.tier)\n| extend UnitCost = \n    case(\n        skuTier == \"PremiumV3\" and skuName == \"P1v3\", 243.09,\n        skuTier == \"PremiumV3\" and skuName == \"P2v3\", 486.18,\n        skuTier == \"PremiumV3\" and skuName == \"P3v3\", 972.36,\n        skuTier == \"PremiumV2\" and skuName == \"P1v2\", 182.50,\n        skuTier == \"PremiumV2\" and skuName == \"P2v2\", 365.00,\n        skuTier == \"PremiumV2\" and skuName == \"P3v2\", 730.00,\n        skuTier == \"Standard\" and skuName == \"S1\", 91.25,\n        skuTier == \"Standard\" and skuName == \"S2\", 182.50,\n        skuTier == \"Standard\" and skuName == \"S3\", 365.00,\n        skuTier == \"Basic\" and skuName == \"B1\", 68.62,\n        skuTier == \"Basic\" and skuName == \"B2\", 137.24,\n        skuTier == \"Basic\" and skuName == \"B3\", 273.75,\n        skuTier == \"IsolatedV2\" and skuName == \"I1v2\", 412.45,\n        skuTier == \"IsolatedV2\" and skuName == \"I2v2\", 824.90,\n        skuTier == \"IsolatedV2\" and skuName == \"I3v2\", 1649.80,\n        skuTier == \"Isolated\" and skuName == \"I1\", 412.45,\n        skuTier == \"Isolated\" and skuName == \"I2\", 824.90,\n        skuTier == \"Isolated\" and skuName == \"I3\", 1649.80,\n        skuTier == \"FlexConsumption\", 0.00,\n        91.25  // Default fallback\n    )\n| extend Basis = strcat(\"App Service Plan - \", skuTier, \"/\", skuName)\n| summarize ForsakenCount = count(), UnitCost = any(UnitCost), Basis = any(Basis)\n| extend rtype = \"microsoft.web/serverfarms\"\n| union(\n    resources\n    | where type =~ 'microsoft.compute/disks'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | extend diskState = tostring(properties.diskState)\n    | where (managedBy == \"\" and diskState != 'ActiveSAS') or (diskState == 'Unattached' and diskState != 'ActiveSAS')\n    | where not(name endswith '-ASRReplica' or name startswith 'ms-asr-' or name startswith 'asrseeddisk-')\n    | where (tags !contains 'kubernetes.io-created-for-pvc') and tags !contains 'ASR-ReplicaDisk' and tags !contains 'asrseeddisk' and tags !contains 'RSVaultBackup'\n    | extend diskTier = tostring(properties.tier)\n    | extend diskSizeGB = toint(properties.diskSizeGB)\n    | extend UnitCost = \n        case(\n            diskTier == \"P1\",  0.75,\n            diskTier == \"P2\",  1.50,\n            diskTier == \"P3\",  3.00,\n            diskTier == \"P4\",  6.39,\n            diskTier == \"P6\",  12.35,\n            diskTier == \"P10\", 23.85,\n            diskTier == \"P15\", 46.00,\n            diskTier == \"P20\", 88.60,\n            diskTier == \"P30\", 163.55,\n            diskTier == \"P40\", 313.44,\n            diskTier == \"P50\", 599.61,\n            diskTier == \"E1\",  0.33,\n            diskTier == \"E2\",  0.66,\n            diskTier == \"E3\",  1.32,\n            diskTier == \"E4\",  2.64,\n            diskTier == \"E6\",  5.28,\n            diskTier == \"E10\", 10.56,\n            diskTier == \"E15\", 21.12,\n            diskTier == \"E20\", 42.24,\n            diskTier == \"E30\", 84.48,\n            diskTier == \"E40\", 168.96,\n            diskTier == \"E50\", 337.92,\n            diskTier == \"S10\", 6.48,\n            diskTier == \"S15\", 12.46,\n            diskTier == \"S20\", 23.94,\n            diskTier == \"S30\", 45.06,\n            diskTier == \"S40\", 85.60,\n            diskTier == \"S50\", 157.68,\n            23.85  // Default fallback (P10 equivalent)\n        )\n    | extend Basis = strcat(\"Disk - \", diskTier, \" (\", tostring(diskSizeGB), \"GB)\")\n    | summarize ForsakenCount = count(), UnitCost = any(UnitCost), Basis = any(Basis)\n    | extend rtype = \"microsoft.compute/disks\"\n)\n| union(\n    resources\n    | where type =~ 'microsoft.network/publicipaddresses'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where properties.ipConfiguration == \"\" and properties.natGateway == \"\" and properties.publicIPPrefix == \"\"\n    | extend skuTier = tostring(sku.tier)\n    | extend UnitCost = iff(skuTier == \"Standard\", 3.65, iff(skuTier == \"Basic\", 2.63, 3.65))\n    | extend Basis = strcat(\"Public IP - \", skuTier)\n    | summarize ForsakenCount = count(), UnitCost = any(UnitCost), Basis = any(Basis)\n    | extend rtype = \"microsoft.network/publicipaddresses\"\n)\n| union(\n    resources\n    | where type =~ 'microsoft.network/loadbalancers'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where properties.backendAddressPools == \"[]\" and properties.inboundNatRules == \"[]\" and properties.outboundRules == \"[]\"\n    | extend skuName = tostring(sku.name)\n    | extend UnitCost = iff(skuName == \"Standard\", 18.25, iff(skuName == \"Basic\", 0.00, 18.25))\n    | extend Basis = strcat(\"Load Balancer - \", skuName)\n    | summarize ForsakenCount = count(), UnitCost = any(UnitCost), Basis = any(Basis)\n    | extend rtype = \"microsoft.network/loadbalancers\"\n)\n| union(\n    resources\n    | where type =~ 'microsoft.network/natgateways'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where isnull(properties.subnets)\n    | extend UnitCost = 32.85\n    | extend Basis = \"NAT Gateway (Standard) - UK South\"\n    | summarize ForsakenCount = count(), UnitCost = any(UnitCost), Basis = any(Basis)\n    | extend rtype = \"microsoft.network/natgateways\"\n)\n| union(\n    resources\n    | where type =~ 'microsoft.network/privatednszones'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where properties.numberOfVirtualNetworkLinks == 0\n    | extend UnitCost = 0.50\n    | extend Basis = \"Private DNS Zone\"\n    | summarize ForsakenCount = count(), UnitCost = any(UnitCost), Basis = any(Basis)\n    | extend rtype = \"microsoft.network/privatednszones\"\n)\n| extend MonthlyWaste = todouble(ForsakenCount) * todouble(UnitCost)\n| where ForsakenCount > 0\n| project \n    [\"Resource Type\"] = rtype,\n    [\"Forsaken Count\"] = ForsakenCount,\n    [\"Unit Cost USD/mo\"] = UnitCost,\n    [\"Est Monthly Waste USD\"] = MonthlyWaste,\n    [\"Pricing Basis\"] = Basis\n| order by [\"Est Monthly Waste USD\"] desc",
              "size": 3,
              "title": "Monthly Waste Estimate (Part 1)",
              "noDataMessage": "No forsaken billable resources found.",
              "showExportToExcel": true,
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "table",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Resource Type",
                    "formatter": 16,
                    "formatOptions": {
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "Forsaken Count",
                    "formatter": 12,
                    "formatOptions": {
                      "palette": "redBright"
                    }
                  },
                  {
                    "columnMatch": "Est Monthly Waste USD",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "redBright",
                      "min": 0,
                      "max": 5000
                    }
                  }
                ],
                "rowLimit": 100,
                "filter": true,
                "labelSettings": [
                  {
                    "columnId": "Resource Type",
                    "label": "Resource Type"
                  },
                  {
                    "columnId": "Forsaken Count",
                    "label": "Forsaken Count"
                  },
                  {
                    "columnId": "Unit Cost USD/mo",
                    "label": "Unit Cost (USD/mo)"
                  },
                  {
                    "columnId": "Est Monthly Waste USD",
                    "label": "Est. Monthly Waste (USD)"
                  },
                  {
                    "columnId": "Pricing Basis",
                    "label": "Pricing Basis"
                  }
                ]
              }
            },
            "name": "cost_main_table_part1"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where type =~ 'microsoft.network/privateendpoints'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend connection = iff(array_length(properties.manualPrivateLinkServiceConnections) > 0, properties.manualPrivateLinkServiceConnections[0], properties.privateLinkServiceConnections[0])\n| extend stateEnum = tostring(connection.properties.privateLinkServiceConnectionState.status)\n| where stateEnum == 'Disconnected'\n| summarize ForsakenCount = count()\n| extend rtype = 'microsoft.network/privateendpoints'\n| extend UnitCost = 7.30\n| extend Basis = 'Private Endpoint (Standard) - UK South'\n| union (\n    resources\n    | where type =~ 'microsoft.network/virtualnetworkgateways'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | extend vpnClientConfiguration = properties.vpnClientConfiguration\n    | extend skuName = tostring(properties.sku.name)\n    | extend Resource = id\n    | join kind=leftouter (\n        resources\n        | where type =~ 'microsoft.network/connections'\n        | mv-expand Resource = pack_array(properties.virtualNetworkGateway1.id, properties.virtualNetworkGateway2.id) to typeof(string)\n        | project Resource, connectionId = id\n    ) on Resource\n    | where isempty(vpnClientConfiguration) and isempty(connectionId)\n    | extend UnitCost = case(\n        skuName == \"VpnGw1\",    138.70,\n        skuName == \"VpnGw2\",    357.70,\n        skuName == \"VpnGw3\",    912.50,\n        skuName == \"VpnGw4\",    1533.00,\n        skuName == \"VpnGw5\",    2664.50,\n        skuName == \"VpnGw1AZ\",  153.30,\n        skuName == \"VpnGw2AZ\",  394.20,\n        skuName == \"VpnGw3AZ\",  1007.40,\n        skuName == \"Basic\",     26.28,\n        138.70  // fallback\n    )\n    | extend Basis = strcat(\"VPN Gateway - \", skuName, \" (UK South)\")\n    | summarize ForsakenCount = count(), UnitCost = any(UnitCost), Basis = any(Basis)\n    | extend rtype = 'microsoft.network/virtualnetworkgateways'\n)\n| union (\n    resources\n    | where type =~ 'microsoft.network/applicationgateways'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | extend SKUName = tostring(properties.sku.name)\n    | extend SKUTier = tostring(properties.sku.tier)\n    | extend AppGwId = tostring(id)\n    | project AppGwId, name, SKUName, SKUTier, type\n    | join (\n        resources\n        | where type =~ 'microsoft.network/applicationgateways'\n        | mvexpand backendPools = properties.backendAddressPools\n        | extend backendIPCount = array_length(backendPools.properties.backendIPConfigurations)\n        | extend backendAddressesCount = array_length(backendPools.properties.backendAddresses)\n        | extend AppGwId = tostring(id)\n        | summarize backendIPCount = sum(backendIPCount), backendAddressesCount = sum(backendAddressesCount) by AppGwId\n    ) on AppGwId\n    | project-away AppGwId1\n    | where (backendIPCount == 0 or isempty(backendIPCount)) and (backendAddressesCount == 0 or isempty(backendAddressesCount))\n    | extend UnitCost = case(\n        SKUTier == \"WAF_v2\",        328.50,  // $0.45/hr * 730h\n        SKUTier == \"Standard_v2\",   182.50,  // $0.25/hr * 730h\n        SKUTier == \"WAF\" and SKUName has \"Large\",   402.89,  // V1 WAF Large $0.5519/hr * 730h (RETIRED Apr 2026)\n        SKUTier == \"WAF\" and SKUName has \"Medium\",  113.30,  // V1 WAF Medium $0.1552/hr * 730h (RETIRED)\n        SKUTier == \"Standard\" and SKUName has \"Large\",   287.77,  // V1 Standard Large $0.3942/hr * 730h (RETIRED)\n        SKUTier == \"Standard\" and SKUName has \"Medium\",   62.93,  // V1 Standard Medium $0.0862/hr * 730h (RETIRED)\n        328.50  // fallback WAF_v2\n    )\n    | extend Basis = strcat(\"Application Gateway - \", SKUTier, \"/\", SKUName, \" (UK South)\")\n    | summarize ForsakenCount = count(), UnitCost = any(UnitCost), Basis = any(Basis)\n    | extend rtype = 'microsoft.network/applicationgateways'\n)\n| extend MonthlyWaste = toreal(ForsakenCount) * UnitCost\n| where ForsakenCount > 0\n| project \n    ['Resource Type'] = rtype,\n    ['Forsaken Count'] = ForsakenCount,\n    ['Unit Cost USD/mo'] = UnitCost,\n    ['Est Monthly Waste USD'] = MonthlyWaste,\n    ['Pricing Basis'] = Basis\n| order by ['Est Monthly Waste USD'] desc",
              "size": 3,
              "title": "Monthly Waste Estimate (Part 2 - High Value)",
              "noDataMessage": "No forsaken billable resources found.",
              "showExportToExcel": true,
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "table",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Resource Type",
                    "formatter": 16,
                    "formatOptions": {
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "Forsaken Count",
                    "formatter": 12,
                    "formatOptions": {
                      "palette": "redBright"
                    }
                  },
                  {
                    "columnMatch": "Est Monthly Waste USD",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "redBright",
                      "min": 0,
                      "max": 5000
                    }
                  }
                ],
                "rowLimit": 100,
                "filter": true,
                "labelSettings": [
                  {
                    "columnId": "Resource Type",
                    "label": "Resource Type"
                  },
                  {
                    "columnId": "Forsaken Count",
                    "label": "Forsaken Count"
                  },
                  {
                    "columnId": "Unit Cost USD/mo",
                    "label": "Unit Cost (USD/mo)"
                  },
                  {
                    "columnId": "Est Monthly Waste USD",
                    "label": "Est. Monthly Waste (USD)"
                  },
                  {
                    "columnId": "Pricing Basis",
                    "label": "Pricing Basis"
                  }
                ]
              }
            },
            "name": "cost_main_table_part2"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where type =~ 'microsoft.sql/servers/elasticpools'\n| where resourceGroup in~ ({ResourceGroup:value})\n| project elasticPoolId = tolower(id), type,\n    skuName = tostring(sku.name),\n    skuTier = tostring(sku.tier),\n    skuCapacity = toint(sku.capacity)\n| join kind=leftouter (\n    resources\n    | where type =~ 'microsoft.sql/servers/databases'\n    | project id, elasticPoolId = tolower(tostring(properties.elasticPoolId))\n) on elasticPoolId\n| summarize databaseCount = countif(id != ''), skuName = any(skuName), skuTier = any(skuTier), skuCapacity = any(skuCapacity) by elasticPoolId, type\n| where databaseCount == 0\n| extend UnitCost = case(\n    // Basic DTU pools - UK South\n    skuTier == \"Basic\" and skuCapacity == 50,    92.78,\n    skuTier == \"Basic\" and skuCapacity == 100,   185.55,\n    skuTier == \"Basic\" and skuCapacity == 200,   371.09,\n    skuTier == \"Basic\" and skuCapacity == 300,   556.63,\n    skuTier == \"Basic\" and skuCapacity == 400,   742.17,\n    skuTier == \"Basic\" and skuCapacity == 800,   1484.34,\n    skuTier == \"Basic\" and skuCapacity == 1200,  2226.50,\n    skuTier == \"Basic\" and skuCapacity == 1600,  2968.67,\n    // Standard DTU pools - UK South\n    skuTier == \"Standard\" and skuCapacity == 50,    138.40,\n    skuTier == \"Standard\" and skuCapacity == 100,   276.80,\n    skuTier == \"Standard\" and skuCapacity == 200,   553.59,\n    skuTier == \"Standard\" and skuCapacity == 300,   830.38,\n    skuTier == \"Standard\" and skuCapacity == 400,   1107.17,\n    skuTier == \"Standard\" and skuCapacity == 800,   2214.34,\n    skuTier == \"Standard\" and skuCapacity == 1200,  3321.50,\n    skuTier == \"Standard\" and skuCapacity == 1600,  4428.67,\n    skuTier == \"Standard\" and skuCapacity == 2000,  5535.84,\n    skuTier == \"Standard\" and skuCapacity == 2500,  6919.80,\n    skuTier == \"Standard\" and skuCapacity == 3000,  8303.76,\n    // Premium DTU pools - UK South\n    skuTier == \"Premium\" and skuCapacity == 125,   855.47,\n    skuTier == \"Premium\" and skuCapacity == 250,   1710.94,\n    skuTier == \"Premium\" and skuCapacity == 500,   3421.88,\n    skuTier == \"Premium\" and skuCapacity == 1000,  6843.76,\n    skuTier == \"Premium\" and skuCapacity == 1500,  10265.63,\n    skuTier == \"Premium\" and skuCapacity == 2000,  13687.50,\n    skuTier == \"Premium\" and skuCapacity == 2500,  17109.38,\n    skuTier == \"Premium\" and skuCapacity == 3000,  20531.25,\n    skuTier == \"Premium\" and skuCapacity == 3500,  23953.13,\n    // vCore General Purpose - Standard-series Gen5 - UK South\n    skuTier == \"GeneralPurpose\" and skuCapacity == 2,   423.75,\n    skuTier == \"GeneralPurpose\" and skuCapacity == 4,   847.50,\n    skuTier == \"GeneralPurpose\" and skuCapacity == 6,   1271.24,\n    skuTier == \"GeneralPurpose\" and skuCapacity == 8,   1694.99,\n    skuTier == \"GeneralPurpose\" and skuCapacity == 10,  2118.74,\n    skuTier == \"GeneralPurpose\" and skuCapacity == 16,  3389.97,\n    skuTier == \"GeneralPurpose\" and skuCapacity == 24,  5084.96,\n    skuTier == \"GeneralPurpose\" and skuCapacity == 32,  6779.94,\n    // vCore Business Critical - Standard-series Gen5 - UK South\n    skuTier == \"BusinessCritical\" and skuCapacity == 4,   2206.19,\n    skuTier == \"BusinessCritical\" and skuCapacity == 6,   3309.29,\n    skuTier == \"BusinessCritical\" and skuCapacity == 8,   4412.38,\n    skuTier == \"BusinessCritical\" and skuCapacity == 10,  5515.48,\n    skuTier == \"BusinessCritical\" and skuCapacity == 16,  8824.76,\n    skuTier == \"BusinessCritical\" and skuCapacity == 24,  13237.14,\n    92.78  // fallback: Basic 50 eDTU minimum\n)\n| extend Basis = strcat(\"SQL Elastic Pool - \", skuTier, \" (\", tostring(skuCapacity), \" eDTU/vCores) - UK South\")\n| summarize ForsakenCount = count(), UnitCost = any(UnitCost), Basis = any(Basis)\n| extend rtype = 'microsoft.sql/servers/elasticpools'\n| extend MonthlyWaste = toreal(ForsakenCount) * UnitCost\n| where ForsakenCount > 0\n| project\n    ['Resource Type'] = rtype,\n    ['Forsaken Count'] = ForsakenCount,\n    ['Unit Cost USD/mo'] = UnitCost,\n    ['Est Monthly Waste USD'] = MonthlyWaste,\n    ['Pricing Basis'] = Basis",
              "size": 3,
              "title": "SQL Elastic Pools Cost Estimate",
              "noDataMessage": "No forsaken SQL Elastic Pools.",
              "showExportToExcel": true,
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "table",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Resource Type",
                    "formatter": 16,
                    "formatOptions": {
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "Forsaken Count",
                    "formatter": 12,
                    "formatOptions": {
                      "palette": "redBright"
                    }
                  },
                  {
                    "columnMatch": "Est Monthly Waste USD",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "redBright",
                      "min": 0,
                      "max": 5000
                    }
                  }
                ],
                "rowLimit": 100,
                "filter": true
              }
            },
            "customWidth": "50",
            "name": "cost_sql_table"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where type =~ 'microsoft.network/ddosprotectionplans'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where isnull(properties.virtualNetworks)\n| summarize ForsakenCount = count()\n| extend rtype = 'microsoft.network/ddosprotectionplans'\n| extend UnitCost = 2944.00\n| extend Basis = 'DDoS Network Protection Plan (covers 100 IPs, +$29.50/extra IP) - UK South'\n| extend MonthlyWaste = toreal(ForsakenCount) * UnitCost\n| where ForsakenCount > 0\n| project\n    ['Resource Type'] = rtype,\n    ['Forsaken Count'] = ForsakenCount,\n    ['Unit Cost USD/mo'] = UnitCost,\n    ['Est Monthly Waste USD'] = MonthlyWaste,\n    ['Pricing Basis'] = Basis\n| order by ['Est Monthly Waste USD'] desc",
              "size": 4,
              "title": "DDoS Protection Plans Cost Estimate",
              "noDataMessage": "No forsaken DDoS Protection Plans",
              "showExportToExcel": true,
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "table",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Resource Type",
                    "formatter": 16,
                    "formatOptions": {
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "Forsaken Count",
                    "formatter": 12,
                    "formatOptions": {
                      "palette": "redBright"
                    }
                  },
                  {
                    "columnMatch": "Est Monthly Waste USD",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "redBright",
                      "min": 0,
                      "max": 5000
                    }
                  }
                ],
                "rowLimit": 100,
                "filter": true
              }
            },
            "customWidth": "50",
            "name": "Hi there!"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where type =~ 'microsoft.web/serverfarms'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.numberOfSites == 0\n| summarize ForsakenCount=count()\n| extend rtype='microsoft.web/serverfarms', UnitCost=55.0, Basis='App Service Plan S1'\n| union (\n    Resources\n    | where type =~ 'microsoft.compute/disks'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | extend diskState=tostring(properties.diskState)\n    | where (managedBy == '' and diskState != 'ActiveSAS') or (diskState == 'Unattached' and diskState != 'ActiveSAS')\n    | where not(name endswith '-ASRReplica' or name startswith 'ms-asr-' or name startswith 'asrseeddisk-')\n    | where (tags !contains 'kubernetes.io-created-for-pvc') and tags !contains 'ASR-ReplicaDisk' and tags !contains 'asrseeddisk' and tags !contains 'RSVaultBackup'\n    | summarize ForsakenCount=count()\n    | extend rtype='microsoft.compute/disks', UnitCost=8.0, Basis='P10 128GB disk'\n)\n| union (\n    Resources\n    | where type =~ 'microsoft.network/publicipaddresses'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where properties.ipConfiguration == '' and properties.natGateway == '' and properties.publicIPPrefix == ''\n    | summarize ForsakenCount=count()\n    | extend rtype='microsoft.network/publicipaddresses', UnitCost=3.65, Basis='Standard Static IP'\n)\n| union (\n    resources\n    | where type =~ 'microsoft.network/loadbalancers'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where properties.backendAddressPools == '[]' and properties.inboundNatRules == '[]' and properties.outboundRules == '[]'\n    | summarize ForsakenCount=count()\n    | extend rtype='microsoft.network/loadbalancers', UnitCost=18.0, Basis='Standard LB'\n)\n| union (\n    resources\n    | where type =~ 'microsoft.network/natgateways'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where isnull(properties.subnets)\n    | summarize ForsakenCount=count()\n    | extend rtype='microsoft.network/natgateways', UnitCost=32.0, Basis='NAT Gateway'\n)\n| union (\n    resources\n    | where type =~ 'microsoft.network/privatednszones'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where properties.numberOfVirtualNetworkLinks == 0\n    | summarize ForsakenCount=count()\n    | extend rtype='microsoft.network/privatednszones', UnitCost=0.5, Basis='Private DNS Zone'\n)\n| extend MonthlyWaste = toreal(ForsakenCount) * UnitCost\n| where ForsakenCount > 0\n| project ['Resource Type']=rtype, ['Forsaken Count']=ForsakenCount, ['Unit Cost USD/mo']=UnitCost, ['Est Monthly Waste USD']=MonthlyWaste, ['Pricing Basis']=Basis\n| order by ['Est Monthly Waste USD'] desc",
              "size": 4,
              "title": "Monthly Waste Distribution",
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "barchart",
              "chartSettings": {
                "yAxis": [
                  "Est Monthly Waste USD"
                ],
                "showLegend": true
              }
            },
            "customWidth": "60",
            "name": "cost_bar_chart"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where type =~ 'microsoft.web/serverfarms'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.numberOfSites == 0\n| summarize ForsakenCount=count()\n| extend rtype='microsoft.web/serverfarms', UnitCost=55.0, Basis='App Service Plan S1'\n| union (\n    Resources\n    | where type =~ 'microsoft.compute/disks'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | extend diskState=tostring(properties.diskState)\n    | where (managedBy == '' and diskState != 'ActiveSAS') or (diskState == 'Unattached' and diskState != 'ActiveSAS')\n    | where not(name endswith '-ASRReplica' or name startswith 'ms-asr-' or name startswith 'asrseeddisk-')\n    | where (tags !contains 'kubernetes.io-created-for-pvc') and tags !contains 'ASR-ReplicaDisk' and tags !contains 'asrseeddisk' and tags !contains 'RSVaultBackup'\n    | summarize ForsakenCount=count()\n    | extend rtype='microsoft.compute/disks', UnitCost=8.0, Basis='P10 128GB disk'\n)\n| union (\n    Resources\n    | where type =~ 'microsoft.network/publicipaddresses'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where properties.ipConfiguration == '' and properties.natGateway == '' and properties.publicIPPrefix == ''\n    | summarize ForsakenCount=count()\n    | extend rtype='microsoft.network/publicipaddresses', UnitCost=3.65, Basis='Standard Static IP'\n)\n| union (\n    resources\n    | where type =~ 'microsoft.network/loadbalancers'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where properties.backendAddressPools == '[]' and properties.inboundNatRules == '[]' and properties.outboundRules == '[]'\n    | summarize ForsakenCount=count()\n    | extend rtype='microsoft.network/loadbalancers', UnitCost=18.0, Basis='Standard LB'\n)\n| union (\n    resources\n    | where type =~ 'microsoft.network/natgateways'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where isnull(properties.subnets)\n    | summarize ForsakenCount=count()\n    | extend rtype='microsoft.network/natgateways', UnitCost=32.0, Basis='NAT Gateway'\n)\n| union (\n    resources\n    | where type =~ 'microsoft.network/privatednszones'\n    | where resourceGroup in~ ({ResourceGroup:value})\n    | where properties.numberOfVirtualNetworkLinks == 0\n    | summarize ForsakenCount=count()\n    | extend rtype='microsoft.network/privatednszones', UnitCost=0.5, Basis='Private DNS Zone'\n)\n| extend MonthlyWaste = toreal(ForsakenCount) * UnitCost\n| where ForsakenCount > 0\n| project ['Resource Type']=rtype, ['Forsaken Count']=ForsakenCount, ['Unit Cost USD/mo']=UnitCost, ['Est Monthly Waste USD']=MonthlyWaste, ['Pricing Basis']=Basis\n| order by ['Est Monthly Waste USD'] desc",
              "size": 4,
              "title": "Waste by Type (Pie)",
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "piechart",
              "chartSettings": {
                "xAxis": "Resource Type",
                "yAxis": [
                  "Forsaken Count"
                ],
                "showLegend": true
              }
            },
            "customWidth": "40",
            "name": "cost_pie_chart"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "mainTab",
        "comparison": "isEqualTo",
        "value": "cost"
      },
      "name": "grp_cost"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 11,
            "content": {
              "version": "LinkItem/1.0",
              "style": "tabs",
              "links": [
                {
                  "id": "c1",
                  "cellValue": "computeTab",
                  "linkTarget": "parameter",
                  "linkLabel": "App Service Plans 💲",
                  "subTarget": "appsp",
                  "style": "link"
                },
                {
                  "id": "c2",
                  "cellValue": "computeTab",
                  "linkTarget": "parameter",
                  "linkLabel": "Availability Sets",
                  "subTarget": "avset",
                  "style": "link"
                }
              ]
            },
            "name": "tabs_compute"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "# Forsaken App Service Plans"
                  },
                  "name": "t_asp"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "[App Service plans](https://learn.microsoft.com/en-us/azure/app-service/overview-hosting-plans) without hosting any apps.",
                    "style": "upsell"
                  },
                  "name": "i_asp"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.web/serverfarms'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.numberOfSites == 0\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.web/serverfarms\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 4,
                    "title": "Total",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": false
                    }
                  },
                  "customWidth": "15",
                  "name": "cnt_asp"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.web/serverfarms'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.numberOfSites == 0\n| summarize count(type) by location",
                    "size": 4,
                    "title": "Count by Location",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_asp_loc"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.web/serverfarms'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.numberOfSites == 0\n| summarize count(type) by tostring(sku.name)",
                    "size": 4,
                    "title": "Count by SKU",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_asp_sku"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.web/serverfarms'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.numberOfSites == 0\n| summarize count(type) by tostring(sku.tier)",
                    "size": 4,
                    "title": "Count by Tier",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_asp_tier"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.web/serverfarms'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.numberOfSites == 0\n| extend Details = pack_all()\n| project subscriptionId, Resource=id, resourceGroup, location, SKU=sku.name, Tier=sku.tier, tags, Details",
                    "size": 3,
                    "title": "Forsaken App Service Plans",
                    "noDataMessage": "No forsaken resources found.",
                    "exportMultipleValues": true,
                    "exportedParameters": [
                      {
                        "fieldName": "Resource",
                        "parameterName": "resources",
                        "parameterType": 5
                      }
                    ],
                    "showExportToExcel": true,
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "table",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "$gen_group",
                          "formatter": 13,
                          "formatOptions": {
                            "linkTarget": "Resource",
                            "showIcon": true
                          }
                        },
                        {
                          "columnMatch": "subscriptionId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "Resource",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "resourceGroup",
                          "formatter": 14,
                          "formatOptions": {
                            "linkTarget": "Resource"
                          }
                        },
                        {
                          "columnMatch": "location",
                          "formatter": 17
                        },
                        {
                          "columnMatch": "Details",
                          "formatter": 7,
                          "formatOptions": {
                            "linkTarget": "CellDetails",
                            "linkLabel": "🔍 View Details",
                            "linkIsContextBlade": true
                          }
                        }
                      ],
                      "rowLimit": 1000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "subscriptionId"
                        ],
                        "expandTopLevel": true,
                        "finalBy": "Resource"
                      }
                    }
                  },
                  "name": "tbl_asp"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "items": [
                      {
                        "type": 1,
                        "content": {
                          "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                          "style": "warning"
                        },
                        "name": "txt_del_asp"
                      },
                      {
                        "type": 11,
                        "content": {
                          "version": "LinkItem/1.0",
                          "style": "list",
                          "links": [
                            {
                              "id": "dl_asp",
                              "cellValue": "{resources}",
                              "linkTarget": "ArmAction",
                              "linkLabel": "⛔ Delete Selected Resource",
                              "style": "primary",
                              "linkIsContextBlade": true,
                              "armActionContext": {
                                "path": "{resources}",
                                "headers": [],
                                "params": [
                                  {
                                    "key": "api-version",
                                    "value": "2021-04-01"
                                  }
                                ],
                                "isLongOperation": true,
                                "httpMethod": "DELETE",
                                "applyToMultipleResourcesParameter": "resources",
                                "title": "Delete App Service Plan",
                                "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                                "actionName": "Delete App Service Plan",
                                "runLabel": "Delete App Service Plan"
                              }
                            }
                          ]
                        },
                        "name": "lnk_del_asp"
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "EnableDeletion",
                    "comparison": "isEqualTo",
                    "value": "true"
                  },
                  "name": "grp_del_asp"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "computeTab",
              "comparison": "isEqualTo",
              "value": "appsp"
            },
            "name": "grp_asp"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "# Forsaken Availability Sets"
                  },
                  "name": "t_avset"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "[Availability Sets](https://learn.microsoft.com/en-us/azure/virtual-machines/availability-set-overview) not associated to any VM or VMSS and not related to Azure Site Recovery.",
                    "style": "upsell"
                  },
                  "name": "i_avset"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/availabilitysets'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.virtualMachines == \"[]\"\n| where not(name endswith '-asr')\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.compute/availabilitysets\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 4,
                    "title": "Total",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": false
                    }
                  },
                  "customWidth": "15",
                  "name": "cnt_avset"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/availabilitysets'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.virtualMachines == \"[]\"\n| where not(name endswith '-asr')\n| summarize count(type) by location",
                    "size": 4,
                    "title": "Count by Location",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_avset_loc"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/availabilitysets'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.virtualMachines == \"[]\"\n| where not(name endswith '-asr')\n| summarize count(type) by tostring(properties.platformFaultDomainCount)",
                    "size": 4,
                    "title": "Count by Fault Domains",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_avset_fd"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/availabilitysets'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.virtualMachines == \"[]\"\n| where not(name endswith '-asr')\n| extend Details = pack_all()\n| project subscriptionId, Resource=id, resourceGroup, location, tags, Details",
                    "size": 3,
                    "title": "Forsaken Availability Sets",
                    "noDataMessage": "No forsaken resources found.",
                    "exportMultipleValues": true,
                    "exportedParameters": [
                      {
                        "fieldName": "Resource",
                        "parameterName": "resources",
                        "parameterType": 5
                      }
                    ],
                    "showExportToExcel": true,
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "table",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "$gen_group",
                          "formatter": 13,
                          "formatOptions": {
                            "linkTarget": "Resource",
                            "showIcon": true
                          }
                        },
                        {
                          "columnMatch": "subscriptionId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "Resource",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "resourceGroup",
                          "formatter": 14,
                          "formatOptions": {
                            "linkTarget": "Resource"
                          }
                        },
                        {
                          "columnMatch": "location",
                          "formatter": 17
                        },
                        {
                          "columnMatch": "Details",
                          "formatter": 7,
                          "formatOptions": {
                            "linkTarget": "CellDetails",
                            "linkLabel": "🔍 View Details",
                            "linkIsContextBlade": true
                          }
                        }
                      ],
                      "rowLimit": 1000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "subscriptionId"
                        ],
                        "expandTopLevel": true,
                        "finalBy": "Resource"
                      }
                    }
                  },
                  "name": "tbl_avset"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "items": [
                      {
                        "type": 1,
                        "content": {
                          "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                          "style": "warning"
                        },
                        "name": "txt_del_avset"
                      },
                      {
                        "type": 11,
                        "content": {
                          "version": "LinkItem/1.0",
                          "style": "list",
                          "links": [
                            {
                              "id": "dl_avset",
                              "cellValue": "{resources}",
                              "linkTarget": "ArmAction",
                              "linkLabel": "⛔ Delete Selected Resource",
                              "style": "primary",
                              "linkIsContextBlade": true,
                              "armActionContext": {
                                "path": "{resources}",
                                "headers": [],
                                "params": [
                                  {
                                    "key": "api-version",
                                    "value": "2019-07-01"
                                  }
                                ],
                                "isLongOperation": true,
                                "httpMethod": "DELETE",
                                "applyToMultipleResourcesParameter": "resources",
                                "title": "Delete Availability Set",
                                "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                                "actionName": "Delete Availability Set",
                                "runLabel": "Delete Availability Set"
                              }
                            }
                          ]
                        },
                        "name": "lnk_del_avset"
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "EnableDeletion",
                    "comparison": "isEqualTo",
                    "value": "true"
                  },
                  "name": "grp_del_avset"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "computeTab",
              "comparison": "isEqualTo",
              "value": "avset"
            },
            "name": "grp_avset"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "mainTab",
        "comparison": "isEqualTo",
        "value": "compute"
      },
      "name": "grp_compute"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 11,
            "content": {
              "version": "LinkItem/1.0",
              "style": "tabs",
              "links": [
                {
                  "id": "s1",
                  "cellValue": "storageTab",
                  "linkTarget": "parameter",
                  "linkLabel": "Managed Disks 💲",
                  "subTarget": "disk",
                  "style": "link"
                },
                {
                  "id": "s2",
                  "cellValue": "storageTab",
                  "linkTarget": "parameter",
                  "linkLabel": "Storage Accounts (Review)",
                  "subTarget": "sa",
                  "style": "link"
                }
              ]
            },
            "name": "tabs_storage"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "# Unattached Managed Disks"
                  },
                  "name": "t_disk"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "Managed disks not attached to any VM. ASR replica disks and Kubernetes PVC disks are excluded. Billed at full provisioned size.",
                    "style": "upsell"
                  },
                  "name": "i_disk"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/disks'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend diskState = tostring(properties.diskState)\n| where (managedBy == '' and diskState != 'ActiveSAS') or (diskState == 'Unattached' and diskState != 'ActiveSAS')\n| where not(name endswith '-ASRReplica' or name startswith 'ms-asr-' or name startswith 'asrseeddisk-')\n| where (tags !contains 'kubernetes.io-created-for-pvc') and tags !contains 'ASR-ReplicaDisk' and tags !contains 'asrseeddisk' and tags !contains 'RSVaultBackup'\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.compute/disks\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 4,
                    "title": "Total",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": false
                    }
                  },
                  "customWidth": "15",
                  "name": "cnt_disk"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/disks'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend diskState = tostring(properties.diskState)\n| where (managedBy == '' and diskState != 'ActiveSAS') or (diskState == 'Unattached' and diskState != 'ActiveSAS')\n| where not(name endswith '-ASRReplica' or name startswith 'ms-asr-' or name startswith 'asrseeddisk-')\n| where (tags !contains 'kubernetes.io-created-for-pvc') and tags !contains 'ASR-ReplicaDisk' and tags !contains 'asrseeddisk' and tags !contains 'RSVaultBackup'\n| summarize count(type) by tostring(sku.name)",
                    "size": 4,
                    "title": "Count by SKU",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_disk_sku"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/disks'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend diskState = tostring(properties.diskState)\n| where (managedBy == '' and diskState != 'ActiveSAS') or (diskState == 'Unattached' and diskState != 'ActiveSAS')\n| where not(name endswith '-ASRReplica' or name startswith 'ms-asr-' or name startswith 'asrseeddisk-')\n| where (tags !contains 'kubernetes.io-created-for-pvc') and tags !contains 'ASR-ReplicaDisk' and tags !contains 'asrseeddisk' and tags !contains 'RSVaultBackup'\n| summarize count(type) by location",
                    "size": 4,
                    "title": "Count by Location",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_disk_loc"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/disks'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend diskState = tostring(properties.diskState)\n| where (managedBy == '' and diskState != 'ActiveSAS') or (diskState == 'Unattached' and diskState != 'ActiveSAS')\n| where not(name endswith '-ASRReplica' or name startswith 'ms-asr-' or name startswith 'asrseeddisk-')\n| where (tags !contains 'kubernetes.io-created-for-pvc') and tags !contains 'ASR-ReplicaDisk' and tags !contains 'asrseeddisk' and tags !contains 'RSVaultBackup'\n| summarize count(type) by diskState",
                    "size": 4,
                    "title": "Count by State",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_disk_state"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "Resources\n| where type =~ 'microsoft.compute/disks'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend diskState = tostring(properties.diskState)\n| where (managedBy == '' and diskState != 'ActiveSAS') or (diskState == 'Unattached' and diskState != 'ActiveSAS')\n| where not(name endswith '-ASRReplica' or name startswith 'ms-asr-' or name startswith 'asrseeddisk-')\n| where (tags !contains 'kubernetes.io-created-for-pvc') and tags !contains 'ASR-ReplicaDisk' and tags !contains 'asrseeddisk' and tags !contains 'RSVaultBackup'\n| extend Details = pack_all()\n| project subscriptionId, Resource=id, resourceGroup, location, SKU=sku.name, SizeGB=tostring(properties.diskSizeGB), DiskState=diskState, tags, Details",
                    "size": 3,
                    "title": "Unattached Managed Disks",
                    "noDataMessage": "No forsaken resources found.",
                    "exportMultipleValues": true,
                    "exportedParameters": [
                      {
                        "fieldName": "Resource",
                        "parameterName": "resources",
                        "parameterType": 5
                      }
                    ],
                    "showExportToExcel": true,
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "table",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "$gen_group",
                          "formatter": 13,
                          "formatOptions": {
                            "linkTarget": "Resource",
                            "showIcon": true
                          }
                        },
                        {
                          "columnMatch": "subscriptionId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "Resource",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "resourceGroup",
                          "formatter": 14,
                          "formatOptions": {
                            "linkTarget": "Resource"
                          }
                        },
                        {
                          "columnMatch": "location",
                          "formatter": 17
                        },
                        {
                          "columnMatch": "Details",
                          "formatter": 7,
                          "formatOptions": {
                            "linkTarget": "CellDetails",
                            "linkLabel": "🔍 View Details",
                            "linkIsContextBlade": true
                          }
                        }
                      ],
                      "rowLimit": 1000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "subscriptionId"
                        ],
                        "expandTopLevel": true,
                        "finalBy": "Resource"
                      }
                    }
                  },
                  "name": "tbl_disk"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "items": [
                      {
                        "type": 1,
                        "content": {
                          "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                          "style": "warning"
                        },
                        "name": "txt_del_disk"
                      },
                      {
                        "type": 11,
                        "content": {
                          "version": "LinkItem/1.0",
                          "style": "list",
                          "links": [
                            {
                              "id": "dl_disk",
                              "cellValue": "{resources}",
                              "linkTarget": "ArmAction",
                              "linkLabel": "⛔ Delete Selected Resource",
                              "style": "primary",
                              "linkIsContextBlade": true,
                              "armActionContext": {
                                "path": "{resources}",
                                "headers": [],
                                "params": [
                                  {
                                    "key": "api-version",
                                    "value": "2022-07-02"
                                  }
                                ],
                                "isLongOperation": true,
                                "httpMethod": "DELETE",
                                "applyToMultipleResourcesParameter": "resources",
                                "title": "Delete Managed Disk",
                                "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                                "actionName": "Delete Managed Disk",
                                "runLabel": "Delete Managed Disk"
                              }
                            }
                          ]
                        },
                        "name": "lnk_del_disk"
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "EnableDeletion",
                    "comparison": "isEqualTo",
                    "value": "true"
                  },
                  "name": "grp_del_disk"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "storageTab",
              "comparison": "isEqualTo",
              "value": "disk"
            },
            "name": "grp_disk"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "# Storage Accounts for Review"
                  },
                  "name": "t_sa"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "**⚠️ IMPORTANT - READ BEFORE DELETING**\n\nStorage Accounts listed here are older than 90 days. **This does NOT automatically mean they are unused.**\n\n**To verify if a storage account is truly abandoned:**\n1. Enable **Diagnostic Settings** for the storage account\n2. Check these log tables in Log Analytics:\n   - `StorageBlobLogs` - for blob container activity\n   - `StorageFileLogs` - for file share access  \n   - `StorageQueueLogs` - for queue operations\n   - `StorageTableLogs` - for table storage queries\n\n**🔍 Example StorageFileLogs entry:**\n```\nOperationName: ListShares | StatusCode: 200 | AuthenticationType: TrustedAccess | CallerIpAddress\n```\n\n**Safe deletion approach:**\n- If **no logs exist** for 30+ days → likely unused (but still verify metrics)\n- If **logs show activity** → DO NOT DELETE\n- When in doubt, keep the storage account\n\n💡 **Note:** Even \"empty\" storage accounts may be used for infrastructure-as-code state files (Terraform), diagnostic logs, or backup metadata.",
                    "style": "warning"
                  },
                  "name": "i_sa"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.storage/storageaccounts'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend createdTime=todatetime(properties.creationTime)\n| extend AgeDays=iff(isnull(createdTime),int(null),datetime_diff('day',now(),createdTime))\n| where AgeDays > 90\n| project subscriptionId, Resource=id, resourceGroup, location, Kind=kind, SKU=tostring(sku.name), ['Access Tier']=tostring(properties.accessTier), ['Age Days']=AgeDays, Details=pack_all()",
                    "size": 3,
                    "title": "Storage Accounts (Created 90+ days ago)",
                    "noDataMessage": "No storage accounts older than 90 days found.",
                    "exportMultipleValues": true,
                    "exportedParameters": [
                      {
                        "fieldName": "Resource",
                        "parameterName": "resources",
                        "parameterType": 5
                      }
                    ],
                    "showExportToExcel": true,
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "table",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "$gen_group",
                          "formatter": 13,
                          "formatOptions": {
                            "linkTarget": "Resource",
                            "showIcon": true
                          }
                        },
                        {
                          "columnMatch": "subscriptionId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "Resource",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "resourceGroup",
                          "formatter": 14,
                          "formatOptions": {
                            "linkTarget": "Resource"
                          }
                        },
                        {
                          "columnMatch": "location",
                          "formatter": 17
                        },
                        {
                          "columnMatch": "Details",
                          "formatter": 7,
                          "formatOptions": {
                            "linkTarget": "CellDetails",
                            "linkLabel": "🔍 View Details",
                            "linkIsContextBlade": true
                          }
                        }
                      ],
                      "rowLimit": 1000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "subscriptionId"
                        ],
                        "expandTopLevel": true,
                        "finalBy": "Resource"
                      }
                    }
                  },
                  "name": "tbl_sa"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "items": [
                      {
                        "type": 1,
                        "content": {
                          "json": "### Delete Resource(s)\n\n⚠️ **WARNING:** Only delete after VERIFYING no activity via diagnostic logs!\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                          "style": "error"
                        },
                        "name": "txt_del_sa"
                      },
                      {
                        "type": 11,
                        "content": {
                          "version": "LinkItem/1.0",
                          "style": "list",
                          "links": [
                            {
                              "id": "dl_sa",
                              "cellValue": "{resources}",
                              "linkTarget": "ArmAction",
                              "linkLabel": "⚠️ DELETE STORAGE ACCOUNT (Verify First!)",
                              "style": "danger",
                              "linkIsContextBlade": true,
                              "armActionContext": {
                                "path": "{resources}",
                                "headers": [],
                                "params": [
                                  {
                                    "key": "api-version",
                                    "value": "2021-09-01"
                                  }
                                ],
                                "isLongOperation": true,
                                "httpMethod": "DELETE",
                                "applyToMultipleResourcesParameter": "resources",
                                "title": "⚠️ DELETE STORAGE ACCOUNT",
                                "description": "# ⛔ DANGER - READ CAREFULLY!\n\n**This will permanently delete:**\n\n{resources}\n\n**This action is IRREVERSIBLE!**\n\n**Before proceeding, CONFIRM:**\n- ✅ You have checked diagnostic logs (StorageBlobLogs, StorageFileLogs, StorageQueueLogs, StorageTableLogs)\n- ✅ No activity has been seen for 30+ days\n- ✅ No infrastructure-as-code (Terraform/Pulumi) uses this for state\n- ✅ No backup or logging solution depends on this account\n\nRequires Contributor role on the Resource Group.\n\n⚠️ **You have been warned!** ⚠️",
                                "actionName": "DELETE Storage Account (Irreversible)",
                                "runLabel": "⚠️ PERMANENTLY DELETE STORAGE ACCOUNT ⚠️"
                              }
                            }
                          ]
                        },
                        "name": "lnk_del_sa"
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "EnableDeletion",
                    "comparison": "isEqualTo",
                    "value": "true"
                  },
                  "name": "grp_del_sa"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "storageTab",
              "comparison": "isEqualTo",
              "value": "sa"
            },
            "name": "grp_sa"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "mainTab",
        "comparison": "isEqualTo",
        "value": "storage"
      },
      "name": "grp_storage"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "# Forsaken SQL Elastic Pools"
            },
            "name": "t_sql"
          },
          {
            "type": 1,
            "content": {
              "json": "[SQL Elastic Pools](https://learn.microsoft.com/en-us/azure/azure-sql/database/elastic-pool-overview) with zero databases. Paying for pooled DTU/vCore capacity serving no workloads.",
              "style": "upsell"
            },
            "name": "i_sql"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where type =~ 'microsoft.sql/servers/elasticpools'\n| where resourceGroup in~ ({ResourceGroup:value})\n| project elasticPoolId = tolower(id), Resource = id, type\n| join kind=leftouter (resources\n  | where type =~ 'microsoft.sql/servers/databases'\n  | project id, properties\n  | extend elasticPoolId = tolower(properties.elasticPoolId)) on elasticPoolId\n| summarize databaseCount = countif(id != '') by Resource, type\n| where databaseCount == 0\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.sql/servers/elasticpools\", 0])\n| summarize total_count = max(count_) by type",
              "size": 4,
              "title": "Total",
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "tiles",
              "tileSettings": {
                "titleContent": {
                  "columnMatch": "type",
                  "formatter": 16,
                  "formatOptions": {
                    "showIcon": true
                  }
                },
                "leftContent": {
                  "columnMatch": "total_count",
                  "formatter": 12,
                  "formatOptions": {
                    "palette": "auto"
                  }
                },
                "showBorder": false
              }
            },
            "customWidth": "15",
            "name": "cnt_sql"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where type =~ 'microsoft.sql/servers/elasticpools'\n| where resourceGroup in~ ({ResourceGroup:value})\n| project elasticPoolId = tolower(id), type, loc=location\n| join kind=leftouter (\n    resources\n    | where type =~ 'microsoft.sql/servers/databases'\n    | project id, elasticPoolId = tolower(tostring(properties.elasticPoolId))\n) on elasticPoolId\n| summarize databaseCount = countif(id != '') by elasticPoolId, type, loc\n| where databaseCount == 0\n| summarize count() by loc",
              "size": 4,
              "title": "Count by Location",
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "piechart",
              "chartSettings": {
                "showMetrics": false,
                "showLegend": true
              }
            },
            "customWidth": "25",
            "name": "pie_sql_loc"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where type =~ 'microsoft.sql/servers/elasticpools'\n| where resourceGroup in~ ({ResourceGroup:value})\n| project elasticPoolId = tolower(id), Resource = id, type, resourceGroup, subscriptionId, location, tags=tostring(tags), Details=tostring(pack_all())\n| join kind=leftouter (\n    resources\n    | where type =~ 'microsoft.sql/servers/databases'\n    | project id, properties\n    | extend elasticPoolId = tolower(tostring(properties.elasticPoolId))\n) on elasticPoolId\n| summarize databaseCount = countif(id != '') by Resource, type, resourceGroup, subscriptionId, location, tags, Details\n| where databaseCount == 0\n| project-away databaseCount\n| project subscriptionId, Resource, resourceGroup, location, tags, Details",
              "size": 3,
              "title": "Forsaken SQL Elastic Pools",
              "noDataMessage": "No forsaken resources found.",
              "exportMultipleValues": true,
              "exportedParameters": [
                {
                  "fieldName": "Resource",
                  "parameterName": "resources",
                  "parameterType": 5
                }
              ],
              "showExportToExcel": true,
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "table",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "$gen_group",
                    "formatter": 13,
                    "formatOptions": {
                      "linkTarget": "Resource",
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "subscriptionId",
                    "formatter": 5
                  },
                  {
                    "columnMatch": "Resource",
                    "formatter": 5
                  },
                  {
                    "columnMatch": "resourceGroup",
                    "formatter": 14,
                    "formatOptions": {
                      "linkTarget": "Resource"
                    }
                  },
                  {
                    "columnMatch": "location",
                    "formatter": 17
                  },
                  {
                    "columnMatch": "Details",
                    "formatter": 7,
                    "formatOptions": {
                      "linkTarget": "CellDetails",
                      "linkLabel": "🔍 View Details",
                      "linkIsContextBlade": true
                    }
                  }
                ],
                "rowLimit": 1000,
                "filter": true,
                "hierarchySettings": {
                  "treeType": 1,
                  "groupBy": [
                    "subscriptionId"
                  ],
                  "expandTopLevel": true,
                  "finalBy": "Resource"
                }
              }
            },
            "name": "tbl_sql"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                    "style": "warning"
                  },
                  "name": "txt_del_sql"
                },
                {
                  "type": 11,
                  "content": {
                    "version": "LinkItem/1.0",
                    "style": "list",
                    "links": [
                      {
                        "id": "dl_sql",
                        "cellValue": "{resources}",
                        "linkTarget": "ArmAction",
                        "linkLabel": "⛔ Delete Selected Resource",
                        "style": "primary",
                        "linkIsContextBlade": true,
                        "armActionContext": {
                          "path": "{resources}",
                          "headers": [],
                          "params": [
                            {
                              "key": "api-version",
                              "value": "2021-11-01"
                            }
                          ],
                          "isLongOperation": true,
                          "httpMethod": "DELETE",
                          "applyToMultipleResourcesParameter": "resources",
                          "title": "Delete SQL Elastic Pool",
                          "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                          "actionName": "Delete SQL Elastic Pool",
                          "runLabel": "Delete SQL Elastic Pool"
                        }
                      }
                    ]
                  },
                  "name": "lnk_del_sql"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "EnableDeletion",
              "comparison": "isEqualTo",
              "value": "true"
            },
            "name": "grp_del_sql"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "mainTab",
        "comparison": "isEqualTo",
        "value": "database"
      },
      "name": "grp_database"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "## Forsaken Network Resources\n\nAll unattached and unassociated network resources in a single view. Grouped by resource type.\n\n💲 marks resources that continue to generate charges even when forsaken.",
              "style": "info"
            },
            "name": "net_info"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Resources\n| where resourceGroup in~ ({ResourceGroup:value})\n| where type in~ (\n    'microsoft.network/publicipaddresses',\n    'microsoft.network/networkinterfaces',\n    'microsoft.network/networksecuritygroups',\n    'microsoft.network/routetables',\n    'microsoft.network/loadbalancers')\n| extend isForsaken = case(\n    type =~ 'microsoft.network/publicipaddresses',\n        iff(properties.ipConfiguration == '' and properties.natGateway == '' and properties.publicIPPrefix == '', true, false),\n    type =~ 'microsoft.network/networkinterfaces',\n        iff(isnull(properties.privateEndpoint) and isnull(properties.privateLinkService) and properties.hostedWorkloads == '[]' and properties !has 'virtualmachine', true, false),\n    type =~ 'microsoft.network/networksecuritygroups',\n        iff(isnull(properties.networkInterfaces) and isnull(properties.subnets), true, false),\n    type =~ 'microsoft.network/routetables',\n        iff(isnull(properties.subnets), true, false),\n    type =~ 'microsoft.network/loadbalancers',\n        iff(properties.backendAddressPools == '[]' and properties.inboundNatRules == '[]' and properties.outboundRules == '[]', true, false),\n    false)\n| where isForsaken == true\n| extend Billable = case(\n    type =~ 'microsoft.network/publicipaddresses', '💲 Yes',\n    type =~ 'microsoft.network/loadbalancers', '💲 Yes',\n    'No')\n| extend Details = pack_all()\n| project subscriptionId, Resource=id, ['Resource Type']=type, resourceGroup, location, Billable, Details",
              "size": 3,
              "title": "Public IPs | NICs | NSGs | Route Tables | Load Balancers",
              "noDataMessage": "No forsaken network resources found.",
              "exportMultipleValues": true,
              "exportedParameters": [
                {
                  "fieldName": "Resource",
                  "parameterName": "resources",
                  "parameterType": 5
                }
              ],
              "showExportToExcel": true,
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "table",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "$gen_group",
                    "formatter": 13,
                    "formatOptions": {
                      "linkTarget": "Resource",
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "subscriptionId",
                    "formatter": 5
                  },
                  {
                    "columnMatch": "Resource",
                    "formatter": 5
                  },
                  {
                    "columnMatch": "Resource Type",
                    "formatter": 16,
                    "formatOptions": {
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "resourceGroup",
                    "formatter": 14,
                    "formatOptions": {
                      "linkTarget": "Resource"
                    }
                  },
                  {
                    "columnMatch": "location",
                    "formatter": 17
                  },
                  {
                    "columnMatch": "Billable",
                    "formatter": 1
                  },
                  {
                    "columnMatch": "Details",
                    "formatter": 7,
                    "formatOptions": {
                      "linkTarget": "CellDetails",
                      "linkLabel": "🔍 Details",
                      "linkIsContextBlade": true
                    }
                  }
                ],
                "rowLimit": 1000,
                "filter": true,
                "hierarchySettings": {
                  "treeType": 1,
                  "groupBy": [
                    "Resource Type"
                  ],
                  "expandTopLevel": true,
                  "finalBy": "Resource"
                }
              }
            },
            "name": "tbl_net_a"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                    "style": "warning"
                  },
                  "name": "txt_del_net_a"
                },
                {
                  "type": 11,
                  "content": {
                    "version": "LinkItem/1.0",
                    "style": "list",
                    "links": [
                      {
                        "id": "dl_net_a",
                        "cellValue": "{resources}",
                        "linkTarget": "ArmAction",
                        "linkLabel": "⛔ Delete Selected Resource",
                        "style": "primary",
                        "linkIsContextBlade": true,
                        "armActionContext": {
                          "path": "{resources}",
                          "headers": [],
                          "params": [
                            {
                              "key": "api-version",
                              "value": "2021-05-01"
                            }
                          ],
                          "isLongOperation": true,
                          "httpMethod": "DELETE",
                          "applyToMultipleResourcesParameter": "resources",
                          "title": "Delete Network Resource",
                          "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                          "actionName": "Delete Network Resource",
                          "runLabel": "Delete Network Resource"
                        }
                      }
                    ]
                  },
                  "name": "lnk_del_net_a"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "EnableDeletion",
              "comparison": "isEqualTo",
              "value": "true"
            },
            "name": "grp_del_net_a"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "resources\n| where resourceGroup in~ ({ResourceGroup:value})\n| where type in~ (\n    'microsoft.network/natgateways',\n    'microsoft.network/privatednszones',\n    'microsoft.network/privateendpoints',\n    'microsoft.network/virtualnetworks',\n    'microsoft.network/ipgroups')\n| extend isForsaken = case(\n    type =~ 'microsoft.network/natgateways',\n        iff(isnull(properties.subnets), true, false),\n    type =~ 'microsoft.network/privatednszones',\n        iff(properties.numberOfVirtualNetworkLinks == 0, true, false),\n    type =~ 'microsoft.network/privateendpoints',\n        iff(tostring(iff(array_length(properties.manualPrivateLinkServiceConnections) > 0,\n            properties.manualPrivateLinkServiceConnections[0],\n            properties.privateLinkServiceConnections[0]).properties.privateLinkServiceConnectionState.status) == 'Disconnected', true, false),\n    type =~ 'microsoft.network/virtualnetworks',\n        iff(properties.subnets == '[]', true, false),\n    type =~ 'microsoft.network/ipgroups',\n        iff(properties.firewalls == '[]' and properties.firewallPolicies == '[]', true, false),\n    false)\n| where isForsaken == true\n| extend Billable = case(\n    type =~ 'microsoft.network/natgateways', '💲 Yes',\n    type =~ 'microsoft.network/privatednszones', '💲 Yes',\n    type =~ 'microsoft.network/privateendpoints', '💲 Yes',\n    'No')\n| extend Details = pack_all()\n| project subscriptionId, Resource=id, ['Resource Type']=type, resourceGroup, location, Billable, Details",
              "size": 3,
              "title": "NAT Gateways | Private DNS | Private Endpoints | VNets | IP Groups",
              "noDataMessage": "No forsaken network resources found.",
              "exportMultipleValues": true,
              "exportedParameters": [
                {
                  "fieldName": "Resource",
                  "parameterName": "resources",
                  "parameterType": 5
                }
              ],
              "showExportToExcel": true,
              "queryType": 1,
              "resourceType": "microsoft.resourcegraph/resources",
              "crossComponentResources": [
                "{Subscription}"
              ],
              "visualization": "table",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "$gen_group",
                    "formatter": 13,
                    "formatOptions": {
                      "linkTarget": "Resource",
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "subscriptionId",
                    "formatter": 5
                  },
                  {
                    "columnMatch": "Resource",
                    "formatter": 5
                  },
                  {
                    "columnMatch": "Resource Type",
                    "formatter": 16,
                    "formatOptions": {
                      "showIcon": true
                    }
                  },
                  {
                    "columnMatch": "resourceGroup",
                    "formatter": 14,
                    "formatOptions": {
                      "linkTarget": "Resource"
                    }
                  },
                  {
                    "columnMatch": "location",
                    "formatter": 17
                  },
                  {
                    "columnMatch": "Billable",
                    "formatter": 1
                  },
                  {
                    "columnMatch": "Details",
                    "formatter": 7,
                    "formatOptions": {
                      "linkTarget": "CellDetails",
                      "linkLabel": "🔍 Details",
                      "linkIsContextBlade": true
                    }
                  }
                ],
                "rowLimit": 1000,
                "filter": true,
                "hierarchySettings": {
                  "treeType": 1,
                  "groupBy": [
                    "Resource Type"
                  ],
                  "expandTopLevel": true,
                  "finalBy": "Resource"
                }
              }
            },
            "name": "tbl_net_b"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                    "style": "warning"
                  },
                  "name": "txt_del_net_b"
                },
                {
                  "type": 11,
                  "content": {
                    "version": "LinkItem/1.0",
                    "style": "list",
                    "links": [
                      {
                        "id": "dl_net_b",
                        "cellValue": "{resources}",
                        "linkTarget": "ArmAction",
                        "linkLabel": "⛔ Delete Selected Resource",
                        "style": "primary",
                        "linkIsContextBlade": true,
                        "armActionContext": {
                          "path": "{resources}",
                          "headers": [],
                          "params": [
                            {
                              "key": "api-version",
                              "value": "2021-05-01"
                            }
                          ],
                          "isLongOperation": true,
                          "httpMethod": "DELETE",
                          "applyToMultipleResourcesParameter": "resources",
                          "title": "Delete Network Resource",
                          "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                          "actionName": "Delete Network Resource",
                          "runLabel": "Delete Network Resource"
                        }
                      }
                    ]
                  },
                  "name": "lnk_del_net_b"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "EnableDeletion",
              "comparison": "isEqualTo",
              "value": "true"
            },
            "name": "grp_del_net_b"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "mainTab",
        "comparison": "isEqualTo",
        "value": "networking"
      },
      "name": "grp_networking"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 11,
            "content": {
              "version": "LinkItem/1.0",
              "style": "tabs",
              "links": [
                {
                  "id": "ab_rg",
                  "cellValue": "abandonedTab",
                  "linkTarget": "parameter",
                  "linkLabel": "Empty Resource Groups",
                  "subTarget": "rg",
                  "style": "link"
                },
                {
                  "id": "ab_conn",
                  "cellValue": "abandonedTab",
                  "linkTarget": "parameter",
                  "linkLabel": "Logic Apps - Last Run Activity",
                  "subTarget": "conn",
                  "style": "link"
                },
                {
                  "id": "ab_cert",
                  "cellValue": "abandonedTab",
                  "linkTarget": "parameter",
                  "linkLabel": "Expired Certificates",
                  "subTarget": "cert",
                  "style": "link"
                },
                {
                  "id": "ab_vngw",
                  "cellValue": "abandonedTab",
                  "linkTarget": "parameter",
                  "linkLabel": "VNet Gateways No Connections 💲",
                  "subTarget": "vngw",
                  "style": "link"
                },
                {
                  "id": "ab_appgw",
                  "cellValue": "abandonedTab",
                  "linkTarget": "parameter",
                  "linkLabel": "App Gateways Empty Backend 💲",
                  "subTarget": "appgw",
                  "style": "link"
                },
                {
                  "id": "ab_tm",
                  "cellValue": "abandonedTab",
                  "linkTarget": "parameter",
                  "linkLabel": "Traffic Manager No Endpoints",
                  "subTarget": "tm",
                  "style": "link"
                }
              ]
            },
            "name": "tabs_abandoned"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "# Empty Resource Groups"
                  },
                  "name": "t_rg"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "Resource Groups containing zero resources. Empty RGs represent uncleaned up RBAC surface and namespace pollution.",
                    "style": "upsell"
                  },
                  "name": "i_rg"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ResourceContainers\n| where type =~ 'microsoft.resources/subscriptions/resourcegroups'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend rgAndSub = strcat(resourceGroup, \"--\", subscriptionId)\n| join kind=leftouter (\n    Resources\n    | extend rgAndSub = strcat(resourceGroup, \"--\", subscriptionId)\n    | summarize count() by rgAndSub\n) on rgAndSub\n| where isnull(count_)\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.resources/subscriptions/resourcegroups\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 4,
                    "title": "Total",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": false
                    }
                  },
                  "customWidth": "15",
                  "name": "cnt_rg"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ResourceContainers\n| where type =~ 'microsoft.resources/subscriptions/resourcegroups'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend rgAndSub = strcat(resourceGroup, \"--\", subscriptionId)\n| join kind=leftouter (\n    Resources\n    | extend rgAndSub = strcat(resourceGroup, \"--\", subscriptionId)\n    | summarize count() by rgAndSub\n) on rgAndSub\n| where isnull(count_)\n| summarize count(type) by location",
                    "size": 4,
                    "title": "Count by Location",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_rg"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ResourceContainers\n| where type =~ 'microsoft.resources/subscriptions/resourcegroups'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend rgAndSub = strcat(resourceGroup, \"--\", subscriptionId)\n| join kind=leftouter (\n    Resources\n    | extend rgAndSub = strcat(resourceGroup, \"--\", subscriptionId)\n    | summarize count() by rgAndSub\n) on rgAndSub\n| where isnull(count_)\n| extend Details = pack_all()\n| project subscriptionId, Resource=id, resourceGroup, location, tags, Details",
                    "size": 3,
                    "title": "Empty Resource Groups",
                    "noDataMessage": "No forsaken resources found.",
                    "exportMultipleValues": true,
                    "exportedParameters": [
                      {
                        "fieldName": "Resource",
                        "parameterName": "resources",
                        "parameterType": 5
                      }
                    ],
                    "showExportToExcel": true,
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "table",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "$gen_group",
                          "formatter": 13,
                          "formatOptions": {
                            "linkTarget": "Resource",
                            "showIcon": true
                          }
                        },
                        {
                          "columnMatch": "subscriptionId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "Resource",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "resourceGroup",
                          "formatter": 14,
                          "formatOptions": {
                            "linkTarget": "Resource"
                          }
                        },
                        {
                          "columnMatch": "location",
                          "formatter": 17
                        },
                        {
                          "columnMatch": "Details",
                          "formatter": 7,
                          "formatOptions": {
                            "linkTarget": "CellDetails",
                            "linkLabel": "🔍 View Details",
                            "linkIsContextBlade": true
                          }
                        }
                      ],
                      "rowLimit": 1000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "subscriptionId"
                        ],
                        "expandTopLevel": true,
                        "finalBy": "Resource"
                      }
                    }
                  },
                  "name": "tbl_rg"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "items": [
                      {
                        "type": 1,
                        "content": {
                          "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                          "style": "warning"
                        },
                        "name": "txt_del_rg"
                      },
                      {
                        "type": 11,
                        "content": {
                          "version": "LinkItem/1.0",
                          "style": "list",
                          "links": [
                            {
                              "id": "dl_rg",
                              "cellValue": "{resources}",
                              "linkTarget": "ArmAction",
                              "linkLabel": "⛔ Delete Selected Resource",
                              "style": "primary",
                              "linkIsContextBlade": true,
                              "armActionContext": {
                                "path": "{resources}",
                                "headers": [],
                                "params": [
                                  {
                                    "key": "api-version",
                                    "value": "2021-04-01"
                                  }
                                ],
                                "isLongOperation": true,
                                "httpMethod": "DELETE",
                                "applyToMultipleResourcesParameter": "resources",
                                "title": "Delete Empty Resource Groups",
                                "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                                "actionName": "Delete Empty Resource Groups",
                                "runLabel": "Delete Empty Resource Groups"
                              }
                            }
                          ]
                        },
                        "name": "lnk_del_rg"
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "EnableDeletion",
                    "comparison": "isEqualTo",
                    "value": "true"
                  },
                  "name": "grp_del_rg"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "abandonedTab",
              "comparison": "isEqualTo",
              "value": "rg"
            },
            "name": "grp_rg"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "# Logic Apps - Last Run Activity\n\nShows all Logic Apps with their last execution time. Logic Apps with no runs in the last 30 days are considered abandoned.\n\n🔴 **Red status** = No runs in over 30 days - likely abandoned\n🟠 **Orange status** = 30-90 days since last run - investigate\n🟡 **Yellow status** = 90-365 days since last run - high risk of abandonment\n🟢 **Green status** = Active (less than 30 days)"
                  },
                  "name": "t_conn"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "**Note:** Only Logic Apps that have EVER run will appear in this list. Disabled Logic Apps that have never run will not appear. To find truly abandoned Logic Apps, look for those with last run time > 30 days ago.",
                    "style": "info"
                  },
                  "name": "i_conn"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "AzureDiagnostics\n| where ResourceProvider == \"MICROSOFT.LOGIC\"\n| where OperationName == \"Microsoft.Logic/workflows/workflowRunCompleted\"\n| where TimeGenerated > ago(730d)\n| where resource_resourceGroupName_s in~ ({ResourceGroup:value})\n| extend workflowName = tostring(resource_workflowName_s)\n| summarize LastRun = max(TimeGenerated) by workflowName\n| where LastRun < ago(30d)\n| summarize count_ = count()\n| extend type = \"Logic Apps (>30d no run)\", total_count = count_\n| project type, total_count",
                    "size": 4,
                    "title": "Total (>30 days no run)",
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 1
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "redBright"
                        }
                      },
                      "showBorder": true
                    }
                  },
                  "customWidth": "15",
                  "name": "cnt_conn"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "AzureDiagnostics\n| where ResourceProvider == \"MICROSOFT.LOGIC\"\n| where OperationName == \"Microsoft.Logic/workflows/workflowRunCompleted\"\n| where TimeGenerated > ago(730d)\n| where resource_resourceGroupName_s in~ ({ResourceGroup:value})\n| extend workflowName = tostring(resource_workflowName_s)\n| extend Location = tostring(location_s)\n| summarize LastRun = max(TimeGenerated) by workflowName, Location\n| where LastRun < ago(30d)\n| summarize Count = count() by Location\n| order by Count desc",
                    "size": 4,
                    "title": "Abandoned Logic Apps by Location",
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_conn"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "AzureDiagnostics\n| where ResourceProvider == \"MICROSOFT.LOGIC\"\n| where OperationName == \"Microsoft.Logic/workflows/workflowRunCompleted\"\n| where TimeGenerated > ago(730d)\n| where resource_resourceGroupName_s in~ ({ResourceGroup:value})\n| extend workflowId = tostring(workflowId_s)\n| extend workflowName = tostring(resource_workflowName_s)\n| extend ResourceGroup = tostring(resource_resourceGroupName_s)\n| extend subscriptionId = tostring(resource_subscriptionId_g)\n| extend location = tostring(location_s)\n| extend status = tostring(status_s)\n| summarize LastRunTime = max(TimeGenerated), TotalRuns = count(), LastStatus = arg_max(TimeGenerated, status) by workflowId, workflowName, ResourceGroup, subscriptionId, location\n| extend DaysSinceLastRun = datetime_diff('day', now(), LastRunTime)\n| extend Status = case(\n    DaysSinceLastRun > 30, \"🔴 ABANDONED (>30 days)\",\n    DaysSinceLastRun > 90, \"🟠 INACTIVE (30-90 days)\",\n    DaysSinceLastRun > 365, \"🟡 HIGH RISK (90-365 days)\",\n    \"🟢 ACTIVE (<30 days)\")\n| project WorkflowName = workflowName, ResourceGroup, Location = location, SubscriptionId = subscriptionId, LastRunTime, DaysSinceLastRun, TotalRuns, LastStatus, Status, WorkflowId = workflowId\n| order by DaysSinceLastRun desc",
                    "size": 3,
                    "title": "Logic Apps - Last Run Activity",
                    "noDataMessage": "No Logic Apps found with run history.",
                    "exportMultipleValues": true,
                    "exportedParameters": [
                      {
                        "fieldName": "WorkflowId",
                        "parameterName": "resources",
                        "parameterType": 5
                      }
                    ],
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "visualization": "table",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "WorkflowName",
                          "formatter": 13,
                          "formatOptions": {
                            "linkTarget": "Resource",
                            "linkColumn": "WorkflowId",
                            "showIcon": true
                          }
                        },
                        {
                          "columnMatch": "SubscriptionId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "WorkflowId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "ResourceGroup",
                          "formatter": 14,
                          "formatOptions": {
                            "linkTarget": "Resource"
                          }
                        },
                        {
                          "columnMatch": "Location",
                          "formatter": 17
                        },
                        {
                          "columnMatch": "LastRunTime",
                          "formatter": 4
                        },
                        {
                          "columnMatch": "DaysSinceLastRun",
                          "formatter": 12,
                          "formatOptions": {
                            "palette": "redBright"
                          }
                        },
                        {
                          "columnMatch": "TotalRuns",
                          "formatter": 12
                        },
                        {
                          "columnMatch": "LastStatus",
                          "formatter": 1
                        },
                        {
                          "columnMatch": "Status",
                          "formatter": 1
                        }
                      ],
                      "rowLimit": 1000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "Status"
                        ],
                        "expandTopLevel": true,
                        "finalBy": "WorkflowName"
                      }
                    }
                  },
                  "name": "tbl_conn"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "abandonedTab",
              "comparison": "isEqualTo",
              "value": "conn"
            },
            "name": "grp_conn"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "# Expired Certificates"
                  },
                  "name": "t_cert"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "App Service certificates past their expiration date. Expired certs will break HTTPS bindings and should be renewed or deleted.",
                    "style": "upsell"
                  },
                  "name": "i_cert"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.web/certificates'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend expiresOn = todatetime(properties.expirationDate)\n| where expiresOn <= now()\n| extend DaysExpired = datetime_diff('day', now(), expiresOn)\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.web/certificates\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 4,
                    "title": "Total",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": false
                    }
                  },
                  "customWidth": "15",
                  "name": "cnt_cert"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.web/certificates'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend expiresOn = todatetime(properties.expirationDate)\n| where expiresOn <= now()\n| extend DaysExpired = datetime_diff('day', now(), expiresOn)\n| summarize count(type) by location",
                    "size": 4,
                    "title": "Count by Location",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_cert"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.web/certificates'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend expiresOn = todatetime(properties.expirationDate)\n| where expiresOn <= now()\n| extend DaysExpired = datetime_diff('day', now(), expiresOn)\n| extend Details = pack_all()\n| project subscriptionId, Resource=id, resourceGroup, location, tags, Details",
                    "size": 3,
                    "title": "Expired Certificates",
                    "noDataMessage": "No forsaken resources found.",
                    "exportMultipleValues": true,
                    "exportedParameters": [
                      {
                        "fieldName": "Resource",
                        "parameterName": "resources",
                        "parameterType": 5
                      }
                    ],
                    "showExportToExcel": true,
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "table",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "$gen_group",
                          "formatter": 13,
                          "formatOptions": {
                            "linkTarget": "Resource",
                            "showIcon": true
                          }
                        },
                        {
                          "columnMatch": "subscriptionId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "Resource",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "resourceGroup",
                          "formatter": 14,
                          "formatOptions": {
                            "linkTarget": "Resource"
                          }
                        },
                        {
                          "columnMatch": "location",
                          "formatter": 17
                        },
                        {
                          "columnMatch": "Details",
                          "formatter": 7,
                          "formatOptions": {
                            "linkTarget": "CellDetails",
                            "linkLabel": "🔍 View Details",
                            "linkIsContextBlade": true
                          }
                        }
                      ],
                      "rowLimit": 1000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "subscriptionId"
                        ],
                        "expandTopLevel": true,
                        "finalBy": "Resource"
                      }
                    }
                  },
                  "name": "tbl_cert"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "items": [
                      {
                        "type": 1,
                        "content": {
                          "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                          "style": "warning"
                        },
                        "name": "txt_del_cert"
                      },
                      {
                        "type": 11,
                        "content": {
                          "version": "LinkItem/1.0",
                          "style": "list",
                          "links": [
                            {
                              "id": "dl_cert",
                              "cellValue": "{resources}",
                              "linkTarget": "ArmAction",
                              "linkLabel": "⛔ Delete Selected Resource",
                              "style": "primary",
                              "linkIsContextBlade": true,
                              "armActionContext": {
                                "path": "{resources}",
                                "headers": [],
                                "params": [
                                  {
                                    "key": "api-version",
                                    "value": "2021-03-01"
                                  }
                                ],
                                "isLongOperation": true,
                                "httpMethod": "DELETE",
                                "applyToMultipleResourcesParameter": "resources",
                                "title": "Delete Expired Certificates",
                                "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                                "actionName": "Delete Expired Certificates",
                                "runLabel": "Delete Expired Certificates"
                              }
                            }
                          ]
                        },
                        "name": "lnk_del_cert"
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "EnableDeletion",
                    "comparison": "isEqualTo",
                    "value": "true"
                  },
                  "name": "grp_del_cert"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "abandonedTab",
              "comparison": "isEqualTo",
              "value": "cert"
            },
            "name": "grp_cert"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "# VNet Gateways No Connections"
                  },
                  "name": "t_vngw"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "VPN/ExpressRoute Gateways with no connections and no P2S VPN client config. VpnGw1 costs ~$280/month idle.",
                    "style": "upsell"
                  },
                  "name": "i_vngw"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/virtualnetworkgateways'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend vpnClientConfiguration = properties.vpnClientConfiguration\n| extend Resource = id\n| join kind=leftouter (\n    resources\n    | where type =~ 'microsoft.network/connections'\n    | mv-expand Resource = pack_array(properties.virtualNetworkGateway1.id, properties.virtualNetworkGateway2.id) to typeof(string)\n    | project Resource, connectionId = id, ConnectionProperties=properties\n) on Resource\n| where isempty(vpnClientConfiguration) and isempty(connectionId)\n| project-away Resource1, connectionId\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/virtualnetworkgateways\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 4,
                    "title": "Total",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": false
                    }
                  },
                  "customWidth": "15",
                  "name": "cnt_vngw"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/virtualnetworkgateways'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend vpnClientConfiguration = properties.vpnClientConfiguration\n| extend Resource = id\n| join kind=leftouter (\n    resources\n    | where type =~ 'microsoft.network/connections'\n    | mv-expand Resource = pack_array(properties.virtualNetworkGateway1.id, properties.virtualNetworkGateway2.id) to typeof(string)\n    | project Resource, connectionId = id, ConnectionProperties=properties\n) on Resource\n| where isempty(vpnClientConfiguration) and isempty(connectionId)\n| project-away Resource1, connectionId\n| summarize count(type) by location",
                    "size": 4,
                    "title": "Count by Location",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_vngw"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/virtualnetworkgateways'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend vpnClientConfiguration = properties.vpnClientConfiguration\n| extend Resource = id\n| join kind=leftouter (\n    resources\n    | where type =~ 'microsoft.network/connections'\n    | mv-expand Resource = pack_array(properties.virtualNetworkGateway1.id, properties.virtualNetworkGateway2.id) to typeof(string)\n    | project Resource, connectionId = id, ConnectionProperties=properties\n) on Resource\n| where isempty(vpnClientConfiguration) and isempty(connectionId)\n| project-away Resource1, connectionId\n| extend Details = pack_all()\n| project subscriptionId, Resource=id, resourceGroup, location, tags, Details",
                    "size": 3,
                    "title": "VNet Gateways No Connections",
                    "noDataMessage": "No forsaken resources found.",
                    "exportMultipleValues": true,
                    "exportedParameters": [
                      {
                        "fieldName": "Resource",
                        "parameterName": "resources",
                        "parameterType": 5
                      }
                    ],
                    "showExportToExcel": true,
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "table",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "$gen_group",
                          "formatter": 13,
                          "formatOptions": {
                            "linkTarget": "Resource",
                            "showIcon": true
                          }
                        },
                        {
                          "columnMatch": "subscriptionId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "Resource",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "resourceGroup",
                          "formatter": 14,
                          "formatOptions": {
                            "linkTarget": "Resource"
                          }
                        },
                        {
                          "columnMatch": "location",
                          "formatter": 17
                        },
                        {
                          "columnMatch": "Details",
                          "formatter": 7,
                          "formatOptions": {
                            "linkTarget": "CellDetails",
                            "linkLabel": "🔍 View Details",
                            "linkIsContextBlade": true
                          }
                        }
                      ],
                      "rowLimit": 1000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "subscriptionId"
                        ],
                        "expandTopLevel": true,
                        "finalBy": "Resource"
                      }
                    }
                  },
                  "name": "tbl_vngw"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "items": [
                      {
                        "type": 1,
                        "content": {
                          "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                          "style": "warning"
                        },
                        "name": "txt_del_vngw"
                      },
                      {
                        "type": 11,
                        "content": {
                          "version": "LinkItem/1.0",
                          "style": "list",
                          "links": [
                            {
                              "id": "dl_vngw",
                              "cellValue": "{resources}",
                              "linkTarget": "ArmAction",
                              "linkLabel": "⛔ Delete Selected Resource",
                              "style": "primary",
                              "linkIsContextBlade": true,
                              "armActionContext": {
                                "path": "{resources}",
                                "headers": [],
                                "params": [
                                  {
                                    "key": "api-version",
                                    "value": "2021-05-01"
                                  }
                                ],
                                "isLongOperation": true,
                                "httpMethod": "DELETE",
                                "applyToMultipleResourcesParameter": "resources",
                                "title": "Delete VNet Gateways No Connections",
                                "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                                "actionName": "Delete VNet Gateways No Connections",
                                "runLabel": "Delete VNet Gateways No Connections"
                              }
                            }
                          ]
                        },
                        "name": "lnk_del_vngw"
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "EnableDeletion",
                    "comparison": "isEqualTo",
                    "value": "true"
                  },
                  "name": "grp_del_vngw"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "abandonedTab",
              "comparison": "isEqualTo",
              "value": "vngw"
            },
            "name": "grp_vngw"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "# App Gateways Empty Backend"
                  },
                  "name": "t_appgw"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "Application Gateways with no backends and no backend IP configurations. Minimum WAF_v2 cost is ~$250/month.",
                    "style": "upsell"
                  },
                  "name": "i_appgw"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/applicationgateways'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend AppGwId = tostring(id)\n| project AppGwId, type\n| join (\n    resources\n    | where type =~ 'microsoft.network/applicationgateways'\n    | mv-expand backendPools = properties.backendAddressPools\n    | extend backendIPCount = array_length(backendPools.properties.backendIPConfigurations)\n    | extend backendAddressesCount = array_length(backendPools.properties.backendAddresses)\n    | extend AppGwId = tostring(id)\n    | summarize backendIPCount = sum(backendIPCount), backendAddressesCount = sum(backendAddressesCount) by AppGwId\n) on AppGwId\n| project-away AppGwId1\n| where (backendIPCount == 0 or isempty(backendIPCount)) and (backendAddressesCount == 0 or isempty(backendAddressesCount))\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/applicationgateways\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 4,
                    "title": "Total",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": false
                    }
                  },
                  "customWidth": "15",
                  "name": "cnt_appgw"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/applicationgateways'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend backendPoolsCount = array_length(properties.backendAddressPools),SKUName= tostring(properties.sku.name), SKUTier= tostring(properties.sku.tier),SKUCapacity=properties.sku.capacity,backendPools=properties.backendAddressPools , AppGwId = tostring(id)\n| project AppGwId, name, SKUName, SKUTier, SKUCapacity, type, subscriptionId, resourceGroup, location, tags\n| join (\n    resources\n    | where type =~ 'microsoft.network/applicationgateways'\n    | mvexpand backendPools = properties.backendAddressPools\n    | extend backendIPCount = array_length(backendPools.properties.backendIPConfigurations)\n    | extend backendAddressesCount = array_length(backendPools.properties.backendAddresses)\n    | extend AppGwId = tostring(id)\n    | summarize backendIPCount = sum(backendIPCount) ,backendAddressesCount=sum(backendAddressesCount) by AppGwId\n) on AppGwId\n| project-away AppGwId1\n| where (backendIPCount == 0 or isempty(backendIPCount)) and (backendAddressesCount==0 or isempty(backendAddressesCount))\n| summarize count(type) by location",
                    "size": 4,
                    "title": "Count by Location",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_appgw"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/applicationgateways'\n| where resourceGroup in~ ({ResourceGroup:value})\n| extend backendPoolsCount = array_length(properties.backendAddressPools),\n         SKUName = tostring(properties.sku.name),\n         SKUTier = tostring(properties.sku.tier),\n         SKUCapacity = properties.sku.capacity,\n         backendPools = properties.backendAddressPools,\n         AppGwId = tostring(id)\n| project AppGwId, Resource=id, name, SKUName, SKUTier, SKUCapacity, type, subscriptionId, resourceGroup, location, tags=tostring(tags)\n| join (\n    resources\n    | where type =~ 'microsoft.network/applicationgateways'\n    | mv-expand backendPools = properties.backendAddressPools\n    | extend backendIPCount = array_length(backendPools.properties.backendIPConfigurations)\n    | extend backendAddressesCount = array_length(backendPools.properties.backendAddresses)\n    | extend AppGwId = tostring(id)\n    | summarize backendIPCount = sum(backendIPCount), backendAddressesCount = sum(backendAddressesCount) by AppGwId\n) on AppGwId\n| project-away AppGwId1\n| where (backendIPCount == 0 or isempty(backendIPCount))\n    and (backendAddressesCount == 0 or isempty(backendAddressesCount))\n| extend Details = tostring(pack_all())\n| project subscriptionId, Resource, resourceGroup, location, tags, Details",
                    "size": 3,
                    "title": "App Gateways Empty Backend",
                    "noDataMessage": "No forsaken resources found.",
                    "exportMultipleValues": true,
                    "exportedParameters": [
                      {
                        "fieldName": "Resource",
                        "parameterName": "resources",
                        "parameterType": 5
                      }
                    ],
                    "showExportToExcel": true,
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "table",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "$gen_group",
                          "formatter": 13,
                          "formatOptions": {
                            "linkTarget": "Resource",
                            "showIcon": true
                          }
                        },
                        {
                          "columnMatch": "subscriptionId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "Resource",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "resourceGroup",
                          "formatter": 14,
                          "formatOptions": {
                            "linkTarget": "Resource"
                          }
                        },
                        {
                          "columnMatch": "location",
                          "formatter": 17
                        },
                        {
                          "columnMatch": "Details",
                          "formatter": 7,
                          "formatOptions": {
                            "linkTarget": "CellDetails",
                            "linkLabel": "🔍 View Details",
                            "linkIsContextBlade": true
                          }
                        }
                      ],
                      "rowLimit": 1000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "subscriptionId"
                        ],
                        "expandTopLevel": true,
                        "finalBy": "Resource"
                      }
                    }
                  },
                  "name": "tbl_appgw"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "items": [
                      {
                        "type": 1,
                        "content": {
                          "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                          "style": "warning"
                        },
                        "name": "txt_del_appgw"
                      },
                      {
                        "type": 11,
                        "content": {
                          "version": "LinkItem/1.0",
                          "style": "list",
                          "links": [
                            {
                              "id": "dl_appgw",
                              "cellValue": "{resources}",
                              "linkTarget": "ArmAction",
                              "linkLabel": "⛔ Delete Selected Resource",
                              "style": "primary",
                              "linkIsContextBlade": true,
                              "armActionContext": {
                                "path": "{resources}",
                                "headers": [],
                                "params": [
                                  {
                                    "key": "api-version",
                                    "value": "2021-05-01"
                                  }
                                ],
                                "isLongOperation": true,
                                "httpMethod": "DELETE",
                                "applyToMultipleResourcesParameter": "resources",
                                "title": "Delete App Gateways Empty Backend",
                                "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                                "actionName": "Delete App Gateways Empty Backend",
                                "runLabel": "Delete App Gateways Empty Backend"
                              }
                            }
                          ]
                        },
                        "name": "lnk_del_appgw"
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "EnableDeletion",
                    "comparison": "isEqualTo",
                    "value": "true"
                  },
                  "name": "grp_del_appgw"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "abandonedTab",
              "comparison": "isEqualTo",
              "value": "appgw"
            },
            "name": "grp_appgw"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "# Traffic Manager No Endpoints"
                  },
                  "name": "t_tm"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "Traffic Manager profiles with zero endpoints configured routing no traffic.",
                    "style": "upsell"
                  },
                  "name": "i_tm"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/trafficmanagerprofiles'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.endpoints == '[]'\n| summarize count_ = count() by type\n| extend count_ = iff(count_ == 0, 0, count_)\n| union (datatable(type:string, count_:long) [\"microsoft.network/trafficmanagerprofiles\", 0])\n| summarize total_count = max(count_) by type",
                    "size": 4,
                    "title": "Total",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "tiles",
                    "tileSettings": {
                      "titleContent": {
                        "columnMatch": "type",
                        "formatter": 16,
                        "formatOptions": {
                          "showIcon": true
                        }
                      },
                      "leftContent": {
                        "columnMatch": "total_count",
                        "formatter": 12,
                        "formatOptions": {
                          "palette": "auto"
                        }
                      },
                      "showBorder": false
                    }
                  },
                  "customWidth": "15",
                  "name": "cnt_tm"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/trafficmanagerprofiles'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.endpoints == '[]'\n| summarize count(type) by location",
                    "size": 4,
                    "title": "Count by Location",
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "piechart",
                    "chartSettings": {
                      "showMetrics": false,
                      "showLegend": true
                    }
                  },
                  "customWidth": "25",
                  "name": "pie_tm"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "resources\n| where type =~ 'microsoft.network/trafficmanagerprofiles'\n| where resourceGroup in~ ({ResourceGroup:value})\n| where properties.endpoints == '[]'\n| extend Details = pack_all()\n| project subscriptionId, Resource=id, resourceGroup, location, tags, Details",
                    "size": 3,
                    "title": "Traffic Manager No Endpoints",
                    "noDataMessage": "No forsaken resources found.",
                    "exportMultipleValues": true,
                    "exportedParameters": [
                      {
                        "fieldName": "Resource",
                        "parameterName": "resources",
                        "parameterType": 5
                      }
                    ],
                    "showExportToExcel": true,
                    "queryType": 1,
                    "resourceType": "microsoft.resourcegraph/resources",
                    "crossComponentResources": [
                      "{Subscription}"
                    ],
                    "visualization": "table",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "$gen_group",
                          "formatter": 13,
                          "formatOptions": {
                            "linkTarget": "Resource",
                            "showIcon": true
                          }
                        },
                        {
                          "columnMatch": "subscriptionId",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "Resource",
                          "formatter": 5
                        },
                        {
                          "columnMatch": "resourceGroup",
                          "formatter": 14,
                          "formatOptions": {
                            "linkTarget": "Resource"
                          }
                        },
                        {
                          "columnMatch": "location",
                          "formatter": 17
                        },
                        {
                          "columnMatch": "Details",
                          "formatter": 7,
                          "formatOptions": {
                            "linkTarget": "CellDetails",
                            "linkLabel": "🔍 View Details",
                            "linkIsContextBlade": true
                          }
                        }
                      ],
                      "rowLimit": 1000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "subscriptionId"
                        ],
                        "expandTopLevel": true,
                        "finalBy": "Resource"
                      }
                    }
                  },
                  "name": "tbl_tm"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "items": [
                      {
                        "type": 1,
                        "content": {
                          "json": "### Delete Resource(s)\n\n⚠️ **Note:** Select resources one at a time due to API limitations. Requires Contributor role on the Resource Group.\n\nSelect a resource above then click Delete.",
                          "style": "warning"
                        },
                        "name": "txt_del_tm"
                      },
                      {
                        "type": 11,
                        "content": {
                          "version": "LinkItem/1.0",
                          "style": "list",
                          "links": [
                            {
                              "id": "dl_tm",
                              "cellValue": "{resources}",
                              "linkTarget": "ArmAction",
                              "linkLabel": "⛔ Delete Selected Resource",
                              "style": "primary",
                              "linkIsContextBlade": true,
                              "armActionContext": {
                                "path": "{resources}",
                                "headers": [],
                                "params": [
                                  {
                                    "key": "api-version",
                                    "value": "2018-08-01"
                                  }
                                ],
                                "isLongOperation": true,
                                "httpMethod": "DELETE",
                                "applyToMultipleResourcesParameter": "resources",
                                "title": "Delete Traffic Manager No Endpoints",
                                "description": "# ⛔ Attention!\n\nThis will permanently delete:\n\n{resources}\n\nRequires Contributor on the Resource Group.",
                                "actionName": "Delete Traffic Manager No Endpoints",
                                "runLabel": "Delete Traffic Manager No Endpoints"
                              }
                            }
                          ]
                        },
                        "name": "lnk_del_tm"
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "EnableDeletion",
                    "comparison": "isEqualTo",
                    "value": "true"
                  },
                  "name": "grp_del_tm"
                }
              ]
            },
            "conditionalVisibility": {
              "parameterName": "abandonedTab",
              "comparison": "isEqualTo",
              "value": "tm"
            },
            "name": "grp_tm"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "mainTab",
        "comparison": "isEqualTo",
        "value": "abandoned"
      },
      "name": "grp_abandoned"
    }
  ],
  "fromTemplateId": "sentinel-UserWorkbook",
  "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json"
}

Class dismissed.

Consent Preferences