Azure Upgrade This skill handles assessment and automated upgrades of existing Azure workloads from one Azure service, hosting plan, or SKU to another — all within Azure. This includes plan/tier upgrades (e.g. Consumption → Flex Consumption), cross-service migrations (e.g. App Service → Container Apps), and SKU changes. It also covers Azure SDK for Java source-code modernization (e.g. legacy Java → modern ). This is NOT for cross-cloud migration — use for that. Triggers | User Intent | Example Prompts | |-------------|-----------------| | Upgrade Azure Functions plan | "Upgrade my function ap…

) { throw 'Could not resolve a valid runtime storage account name.' }\n $storage = az graph query -q \"resources | where type =~ 'microsoft.storage/storageaccounts' | where name =~ '$storageName' | project name, resourceGroup, subscriptionId, id\" --query \"data[0]\" -o json | ConvertFrom-Json\n if ($null -eq $storage) { throw \"Runtime storage account '$storageName' was not found in accessible subscriptions.\" }\n $storage | ConvertTo-Json\n Write-Output \"Runtime storage authentication: $storageAuthMode\"\n}\nfinally {\n $storageConnection = $null\n}\n```\n\nRecord the safe `name`, `resourceGroup`, `subscriptionId`, `id`, and authentication mode. Never record or display the connection string. If the account cannot be resolved uniquely, stop and ask the user for its resource ID.\n\nFile share mount metadata:\n\n```bash\naz webapp config storage-account list --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[].{customId:name,accountName:value.accountName,shareName:value.shareName,type:value.type,mountPath:value.mountPath,state:value.state}\" -o table\n```\n\nRecord the custom ID, storage account name, share name, type, and mount path for every result. Windows Consumption doesn't support explicit storage mounts, even though the control plane can retain and return this metadata. Catalog it as **not migrated** and explain that it might be stale or never exercised by the source runtime. Don't retrieve storage keys or configure a target mount.\n\nCustom domains (excluding the default `*.azurewebsites.net`):\n\n```bash\naz functionapp config hostname list --webapp-name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?!contains(name, 'azurewebsites.net')]\" --output table\n```\n\nCORS settings:\n\n```bash\naz functionapp cors show --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP>\n```\n\n### 3b. Identify Managed Identities and Role Assignments\n\nGet the system-assigned identity's principal ID:\n\n```bash\naz functionapp identity show --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query principalId -o tsv\n```\n\n> If the principal ID above is non-empty, list its role assignments (substitute `\u003cPRINCIPAL_ID>`):\n\n```bash\naz role assignment list --assignee \u003cPRINCIPAL_ID> --all\n```\n\nList user-assigned managed identities attached to the app:\n\n```bash\naz functionapp identity show --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query userAssignedIdentities -o json\n```\n\n> For each identity in the output, copy its `principalId` and list its role assignments using the same `az role assignment list --assignee \u003cPRINCIPAL_ID> --all` command above.\n\n### 3c. Check Built-in Authentication\n\n```bash\naz webapp auth show --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"{enabled:enabled,unauthenticatedClientAction:unauthenticatedClientAction,defaultProvider:defaultProvider,tokenStoreEnabled:tokenStoreEnabled,allowedAudiences:allowedAudiences,allowedExternalRedirectUrls:allowedExternalRedirectUrls,isAuthFromFile:isAuthFromFile,providers:{aadClientId:clientId,githubClientId:gitHubClientId,googleClientId:googleClientId,facebookAppId:facebookAppId,twitterConsumerKey:twitterConsumerKey,microsoftAccountClientId:microsoftAccountClientId}}\" -o json\n```\n\nRecord only this nonsecret summary. Never query, display, or persist provider secret fields. If `isAuthFromFile` is true or the source uses a provider not represented by this projection, record that provider discovery requires manual review without displaying the auth file. Built-in authentication is handled in [Step 4f.auth](built-in-authentication.md#4fauth-configure-built-in-authentication).\n\n### 3d. Review Inbound Access Restrictions\n\n```bash\naz functionapp config access-restriction show --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7341,"content_sha256":"aef82dad3df709450fd48353c6a87f9aeb2439d108b301f29ca2c2430378f2d3"},{"filename":"references/services/functions/consumption-to-flex/windows/automation/deployment-package.md","content":"# Deployment Package\n\n### 3e. Get Deployment Package (if needed)\n\nIdeally your project files are in source control and you can redeploy from there. If not, you can fetch the active package directly from the source app.\n\n#### Check WEBSITE_RUN_FROM_PACKAGE\n\n**Bash:**\n\n```bash\nUPGRADE_DIR=\u003cUPGRADE_DIR>\nrunFromPackage=$(az functionapp config appsettings list --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?name=='WEBSITE_RUN_FROM_PACKAGE'].value | [0]\" -o tsv)\nif [[ \"$runFromPackage\" =~ ^https:// ]]; then\n curl --fail --location --silent --show-error --output \"$UPGRADE_DIR/source-package.zip\" \"$runFromPackage\"\n echo \"Downloaded the remote deployment package without displaying its URL.\"\nelif [[ \"$runFromPackage\" == \"1\" ]]; then\n echo \"The package is stored in the app content share.\"\nelse\n echo \"The app is not configured for run-from-package.\"\nfi\nunset runFromPackage\n```\n\n**PowerShell 7:**\n\n```powershell\n$runFromPackage = $null\ntry {\n $upgradeDir = '\u003cUPGRADE_DIR>'\n $runFromPackage = az functionapp config appsettings list --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?name=='WEBSITE_RUN_FROM_PACKAGE'].value | [0]\" -o tsv\n if ($LASTEXITCODE -ne 0) { throw 'Failed to read WEBSITE_RUN_FROM_PACKAGE.' }\n $runFromPackage = ([string]$runFromPackage).Trim()\n if ($runFromPackage -match '^https://') {\n Invoke-WebRequest -Uri $runFromPackage -OutFile (Join-Path $upgradeDir 'source-package.zip') -ErrorAction Stop\n Write-Output 'Downloaded the remote deployment package without displaying its URL.'\n }\n elseif ($runFromPackage -eq '1') {\n Write-Output 'The package is stored in the app content share.'\n }\n else {\n Write-Output 'The app is not configured for run-from-package.'\n }\n}\nfinally {\n $runFromPackage = $null\n}\n```\n\nInterpret the classification:\n\n- **Remote package downloaded** → use `\u003cUPGRADE_DIR>/source-package.zip` in Step 5. Skip the rest of this section.\n- **`1`** → the package lives in the app's content file share. Continue below.\n- **Empty** → not run-from-package. Either redeploy from source or capture the project files via Kudu (`https://\u003cAPP_NAME>.scm.azurewebsites.net`); package retrieval steps below do not apply.\n\n#### Download the package from the content file share\n\n> 🔒 **Security**: `AzureWebJobsStorage` contains the storage account key. Keep it out of command arguments and output by using the Azure CLI's `AZURE_STORAGE_CONNECTION_STRING` environment variable in a scoped block. The cleanup below runs on success or failure.\n>\n> ⚠️ **Skill instruction**: Do NOT request the value of `AzureWebJobsStorage`, `WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`, or any other connection string from the user. The commands below get them automatically without exposing them.\n\nGet the content share name (not a secret — safe to display):\n\n```bash\naz functionapp config appsettings list --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?name=='WEBSITE_CONTENTSHARE'].value\" -o tsv\n```\n\nSave the output as `\u003cCONTENT_SHARE>` for the commands below.\n\n> 📁 The download commands below write to `\u003cUPGRADE_DIR>` (default: `.azure-upgrade/\u003csource-app-name>/`). See [Artifact Output Policy](../../../../../global-rules.md#artifact-output-policy). Resolve `\u003cUPGRADE_DIR>` once at session start and create the directory before running these commands.\n\nDownload the pointer file and active package in one scoped block. The package filename is not secret and is printed so it can be reused as `\u003cPACKAGE_NAME>` in Step 5.\n\n**Bash:**\n\n```bash\n(\n set -e\n trap 'unset AZURE_STORAGE_CONNECTION_STRING' EXIT\n export AZURE_STORAGE_CONNECTION_STRING=$(az functionapp config appsettings list --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?name=='AzureWebJobsStorage'].value\" -o tsv)\n az storage file download --share-name \u003cCONTENT_SHARE> --path data/SitePackages/packagename.txt --dest \u003cUPGRADE_DIR> --no-progress --output none\n PACKAGE_NAME=$(cat \u003cUPGRADE_DIR>/packagename.txt)\n az storage file download --share-name \u003cCONTENT_SHARE> --path \"data/SitePackages/$PACKAGE_NAME\" --dest \u003cUPGRADE_DIR> --no-progress --output none\n rm \u003cUPGRADE_DIR>/packagename.txt\n printf 'Downloaded package: %s\\n' \"$PACKAGE_NAME\"\n)\n```\n\n**PowerShell 7:**\n\n```powershell\n$previousConnectionString = $env:AZURE_STORAGE_CONNECTION_STRING\ntry {\n $env:AZURE_STORAGE_CONNECTION_STRING = az functionapp config appsettings list --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?name=='AzureWebJobsStorage'].value\" -o tsv\n if ([string]::IsNullOrWhiteSpace($env:AZURE_STORAGE_CONNECTION_STRING)) { throw 'AzureWebJobsStorage was not found.' }\n az storage file download --share-name \u003cCONTENT_SHARE> --path data/SitePackages/packagename.txt --dest \u003cUPGRADE_DIR> --no-progress --output none\n if ($LASTEXITCODE -ne 0) { throw 'Failed to download packagename.txt.' }\n $packageName = (Get-Content \u003cUPGRADE_DIR>/packagename.txt -Raw).Trim()\n az storage file download --share-name \u003cCONTENT_SHARE> --path \"data/SitePackages/$packageName\" --dest \u003cUPGRADE_DIR> --no-progress --output none\n if ($LASTEXITCODE -ne 0) { throw 'Failed to download the deployment package.' }\n Remove-Item \u003cUPGRADE_DIR>/packagename.txt\n Write-Output \"Downloaded package: $packageName\"\n}\nfinally {\n $env:AZURE_STORAGE_CONNECTION_STRING = $previousConnectionString\n $previousConnectionString = $null\n}\n```\n\n> 💡 The package is a regular `.zip` file — deploy it to the new Flex Consumption app with `az functionapp deployment source config-zip --src \u003cPACKAGE_NAME>` in Step 5. (Linux Consumption uses a different format — `squashfs` in the `scm-releases` blob container — that pattern does NOT apply here.)\n>\n> 💡 If your storage account is configured for Entra-ID-only auth and the connection string lookup fails, retrieve the account name with `az functionapp show --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"storageAccount\" -o tsv` and re-run the file commands with `--account-name \u003cNAME> --auth-mode login` (requires `Storage File Data Privileged Reader` on the share).\n\n---\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6144,"content_sha256":"8e0bea27c81a57ecb74b24d355efb7d2862d6bd900a91a7f48c8851813c918b0"},{"filename":"references/services/functions/consumption-to-flex/windows/automation/discovery-and-assessment.md","content":"# Discovery and Assessment\n\n## Prerequisites\n\n```bash\n# Verify the Azure CLI version\naz version --query '\"azure-cli\"' -o tsv\n\n# Install required CLI extensions\naz extension add --name resource-graph\naz extension add --name application-insights\n\n# Login and set subscription\naz login\naz account set --subscription \u003cSUBSCRIPTION_ID>\n```\n\nIf `az` is unavailable, stop and provide Azure CLI installation guidance. If the reported version is lower than `2.77.0`, stop and require an upgrade before running migration commands. When using the Bash path, also run `jq --version` before the first Bash block that uses `jq`; stop with installation guidance if it is unavailable. PowerShell 7 uses `ConvertFrom-Json` and does not require `jq`.\n\n---\n\n## Step 1: Identify Candidate Apps\n\nUse a single Azure Resource Graph query to list all Windows function apps running on a Consumption (Y1/Dynamic) plan in the current subscription:\n\n```bash\naz graph query -q \"resources | where subscriptionId == '$(az account show --query id -o tsv)' | where type == 'microsoft.web/sites' | where ['kind'] == 'functionapp' | where properties.sku == 'Dynamic' | project name, location, resourceGroup\" --query data --output table\n```\n\nThis returns app name, location, and resource group for every Windows Consumption (Y1) function app. The `kind == 'functionapp'` filter excludes Linux apps (`functionapp,linux`) and the `properties.sku == 'Dynamic'` filter excludes Premium / Dedicated / Isolated / Flex Consumption.\n\n> 💡 The `$(az account show --query id -o tsv)` sub-expression works in both bash and PowerShell. The `--subscriptions` flag also accepts an explicit subscription ID if you want to target a different sub.\n\n---\n\n## Step 2: Assessment Checks\n\nRun these checks against each candidate app from Step 1.\n\n### 2a. Confirm Region Compatibility\n\n```bash\n# List all regions where Flex Consumption is available\naz functionapp list-flexconsumption-locations --query \"sort_by(@, &name)[].{Region:name}\" -o table\n```\n\n### 2b. Verify Language Stack Compatibility\n\nRead the runtime and Functions host generation from app settings:\n\n```bash\naz functionapp config appsettings list --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?name=='FUNCTIONS_WORKER_RUNTIME' || name=='FUNCTIONS_EXTENSION_VERSION'].{N:name,V:value}\" -o table\n```\n\nPass criteria:\n\n- `FUNCTIONS_WORKER_RUNTIME` is one of: `dotnet-isolated`, `node`, `java`, `python`, `powershell`, `go`, `custom`.\n- `FUNCTIONS_EXTENSION_VERSION` is `~4`.\n\n**Not supported**: `dotnet` (in-process) — must migrate to isolated first. Any `FUNCTIONS_EXTENSION_VERSION` other than `~4` is a blocker.\n\nThe CLI only returns the stored values; the supported-list comparison is yours to make. Capture the runtime as `\u003cRUNTIME>` for Step 2c. `FUNCTIONS_EXTENSION_VERSION` is the Functions host generation, not the language runtime version used by `az functionapp create --runtime-version`.\n\n### 2c. Verify Stack Version Compatibility\n\nFirst collect source-version signals. These values can be empty or stale and are evidence only; `FUNCTIONS_WORKER_RUNTIME_VERSION` is not guaranteed to be present and must not be treated as authoritative:\n\n```bash\naz functionapp config appsettings list --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?name=='FUNCTIONS_WORKER_RUNTIME_VERSION' || name=='WEBSITE_NODE_DEFAULT_VERSION'].{name:name,value:value}\" -o table\naz functionapp config show --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"{netFrameworkVersion:netFrameworkVersion,javaVersion:javaVersion,nodeVersion:nodeVersion,powerShellVersion:powerShellVersion}\" -o table\n```\n\nCheck the versions supported for `\u003cRUNTIME>` in the source app's region:\n\n```bash\naz functionapp list-flexconsumption-runtimes --location \u003cREGION> --runtime \u003cRUNTIME> --query \"[].version\" -o tsv\n```\n\nResolve `\u003cTARGET_RUNTIME_VERSION>` from the strongest available evidence: source project metadata, then deployed-package metadata, then the Azure configuration signals above. Examples include `.csproj` `TargetFramework`, `package.json` `engines.node`, `pom.xml` or Gradle Java toolchain, `pyproject.toml`/`runtime.txt`, and `go.mod`.\n\nRequire the resolved value to exactly match one of the supported versions returned by the command. If the evidence is missing, conflicting, or maps to multiple supported versions, use `ask_user` to show the evidence and supported values and have the user select the intended target version. Explain that selecting a different language version can require code or dependency changes. Record both `\u003cRUNTIME>` and `\u003cTARGET_RUNTIME_VERSION>` in the assessment report and upgrade status; do not guess or default to the newest version.\n\n### 2d. Check Deployment Slots\n\n```bash\naz functionapp deployment slot list --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --output table\n```\n\nIf this returns entries, the app has slots. Flex Consumption does NOT support slots — plan accordingly.\n\n### 2e. Check TLS/SSL Certificates\n\nList certificates available in the source app's resource group:\n\n```bash\naz webapp config ssl list --resource-group \u003cRESOURCE_GROUP> --output table\n```\n\nIf this returns output, determine which certificates the source app actually uses. Record whether each used certificate is private or public and confirm the target can fit within the Flex Consumption limit of three private and three public certificates per app. Plan to re-add them using the documented [site-scoped certificate process](https://learn.microsoft.com/en-us/azure/azure-functions/flex-consumption-how-to#configure-site-scoped-certificates).\n\n`WEBSITE_LOAD_CERTIFICATES` is not used by Flex Consumption. Code that accesses the Windows certificate store must instead load accessible certificates from `/var/ssl/certs` for public certificates or `/var/ssl/private` for private certificates.\n\n### 2f. Check Blob Storage Triggers\n\nFind blob triggers NOT using EventGrid source:\n\n```bash\naz functionapp function list --name \u003cAPP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[].{Function:name, BlobTrigger:(config.bindings[?type=='blobTrigger'] | [0])} | [?BlobTrigger && BlobTrigger.source!='EventGrid'].{Function:Function, TriggerType:BlobTrigger.type, Source:BlobTrigger.source}\" --output table\n```\n\nIf this returns rows, those blob triggers must change from `LogsAndContainerScan` to `EventGrid` before upgrading, subject to the delivery check below.\n\nFor all Blob triggers, inspect the planned target inbound configuration (or the existing target's public network access, private endpoints, and main-site access restrictions). Event Grid push delivery [can't deliver through private endpoints](https://learn.microsoft.com/en-us/azure/event-grid/consume-private-endpoints); outbound VNet integration with storage does not provide inbound event delivery.\n\nBefore recommending conversion, use `ask_user` to agree on a supported Event Grid delivery path. A private-only target without one, unreadable target networking configuration, or an unresolved delivery requirement is a blocker; record it in the assessment and progress status. Do not enable public access or relax restrictions automatically. Check the agreed configuration when applying [target access restrictions](networking-and-storage.md#4i-migrate-access-restrictions) and report any unverified runtime delivery during [cutover](validation-and-cutover.md#per-function-cutover-event-driven-triggers).\n\n### 2g. Source Code Windows Dependency Scan\n\nRecommended for every Windows → Flex migration. Prefer the local source directory or a checked-out repository because project manifests and API usage are directly inspectable. Use the deployed package retrieved in [Step 3e](deployment-package.md#3e-get-deployment-package-if-needed) only when source is unavailable; it confirms what is running but compiled artifacts may reduce scan coverage. The scan checks for Windows-only APIs, packages, registry/cert-store/COM/WMI usage, Windows-RID targeting, Windows-only PowerShell modules, and shell-outs to Windows tools.\n\nBefore concluding that source is unavailable, use `ask_user` to request a local source directory or checked-out repository path. Do not assume the current workspace contains the function app. If the user cannot provide source, offer to download the deployed package or skip the scan.\n\nThe agent dispatches per-language scanning automatically from the `FUNCTIONS_WORKER_RUNTIME` value captured in [Step 2b](#2b-verify-language-stack-compatibility) — no separate language input needed.\n\nFollow the full procedure (inputs, pattern sets for all seven worker runtimes, severity rubric, output model, §11 report section) in [dependency-scan.md](../dependency-scan.md).\n\n> ⚠️ **Skill instruction**: Announce the scan to the user before running it, **and tell them the scan is a heuristic aid only — it pattern-matches the most common Windows-only APIs, packages, and shell-outs but is not exhaustive. The user remains responsible for verifying their code has no Windows dependencies.** If they decline, write *\"User declined the source code dependency scan\"* to §11 of the assessment report and proceed — this scan is **never** a hard gate. Any `Blocker` findings advisorily flip §1 Upgrade Readiness to `Needs Attention`; the user always decides whether to proceed.\n\n---\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9305,"content_sha256":"c544c1501c3d2d6143aa332825889e0f0a02db563eb22a38ca646ff0ffa0bc0e"},{"filename":"references/services/functions/consumption-to-flex/windows/automation/networking-and-storage.md","content":"# Networking and Storage\n\n### 4g. Migrate CORS Settings\n\nGet CORS origins from the source app:\n\n```bash\naz functionapp cors show --name \u003cSOURCE_APP_NAME> --resource-group \u003cSOURCE_RESOURCE_GROUP> --query allowedOrigins -o tsv\n```\n\nAdd each origin to the new app (repeat per origin):\n\n```bash\naz functionapp cors add --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --allowed-origins \u003cORIGIN>\n```\n\n### 4h. Migrate Custom Domains\n\nList custom domains on the source app (excluding the default `*.azurewebsites.net`):\n\n```bash\naz functionapp config hostname list --webapp-name \u003cSOURCE_APP_NAME> --resource-group \u003cSOURCE_RESOURCE_GROUP> --query \"[?!contains(name, 'azurewebsites.net')].name\" -o tsv\n```\n\nAdding a hostname binding does not update its DNS record or move traffic to the target. Verify domain ownership as described in [Migrate an active DNS name](https://learn.microsoft.com/en-us/azure/app-service/manage-custom-dns-migrate-domain), then attempt to add each domain to the new app (repeat per domain):\n\n```bash\naz functionapp config hostname add --webapp-name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --hostname \u003cCUSTOM_DOMAIN>\n```\n\nIf Azure rejects the binding because the hostname cannot be assigned to both apps, stop and record custom-domain migration as deferred. Do not remove the source binding, change DNS, or alter its certificate during this replication phase.\n\n### 4i. Migrate Access Restrictions\n\nGet access restrictions from the source app:\n\n```bash\naz functionapp config access-restriction show --name \u003cSOURCE_APP_NAME> --resource-group \u003cSOURCE_RESOURCE_GROUP> -o json\n```\n\nFor Blob/Event Grid triggers, first check the target's public network access and the complete proposed main-site rule set, including fallback actions, against the Event Grid delivery path agreed in [Step 2f](discovery-and-assessment.md#2f-check-blob-storage-triggers). Event Grid push delivery cannot reach a private-only endpoint; outbound VNet integration does not resolve this. If the configuration cannot be read or the proposed restrictions would block delivery, stop and record Step 4i as blocked. Use `ask_user` to resolve the delivery design; do not automatically enable public access or relax restrictions.\n\nRecreate every explicit main-site rule, preserving its name, action, priority, description, and selector. Skip platform-generated fallback rows with priority `2147483647` (`Allow all` or `Deny all`); default actions are applied separately below.\n\n```bash\naz functionapp config access-restriction add --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --rule-name \u003cRULE_NAME> --action \u003cAllow|Deny> --priority \u003cPRIORITY> --description \"\u003cDESCRIPTION>\" --ip-address \u003cIP_CIDR>\n```\n\nUse exactly one selector matching the source rule:\n\n- IP/CIDR: `--ip-address \u003cIP_CIDR>`\n- Service tag: `--service-tag \u003cSERVICE_TAG>`\n- Virtual-network subnet: `--subnet \u003cSUBNET_RESOURCE_ID>`\n\nIf the source has explicit SCM rules and `scmIpSecurityRestrictionsUseMain` is `false`, recreate them with the same command plus `--scm-site true`.\n\nAfter all explicit rules are present, apply the captured fallback behavior. Set default actions last so the target remains reachable while rules are being added:\n\n```bash\naz functionapp config access-restriction set --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --default-action \u003cMAIN_DEFAULT_ACTION> --scm-default-action \u003cSCM_DEFAULT_ACTION> --use-same-restrictions-for-scm-site \u003ctrue|false>\n```\n\n> ⚠️ **Skill instruction**: Before setting a default action to `Deny`, verify that an explicit allow rule covers the user's smoke-test client and that required deployment traffic can still reach SCM. Use `ask_user` to list the rules and fallback actions being applied. Do not migrate platform-generated fallback rows as ordinary rules.\n\nVerify actions, priorities, selectors, descriptions, default actions, and SCM behavior:\n\n```bash\naz functionapp config access-restriction show --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> -o json\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4011,"content_sha256":"cffe5d4d30a38fddec26550b1b23378571a0566a6520d2e662b58e4db4dbfc5f"},{"filename":"references/services/functions/consumption-to-flex/windows/automation/site-and-identity.md","content":"# Site and Identity Configuration\n\n### 4d. Apply Site Configurations\n\nApply the site-level settings collected in Step 3a. Each command below corresponds to one field from the `az functionapp config show` output (and one from the SCM basic publishing query). **Run only the commands whose source value was non-null** — skipping a command leaves the new app at its Flex default for that field.\n\n> 💡 Source-of-truth mapping: every value below comes directly from Step 3a. Do not re-query the source app — use the values you already captured.\n\nHTTP/2 (`http20Enabled`):\n\n```bash\naz functionapp config set --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --http20-enabled \u003ctrue|false>\n```\n\nMinimum TLS version (`minTlsVersion`, e.g. `1.2` or `1.3`):\n\n```bash\naz functionapp config set --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --min-tls-version \u003cMIN_TLS_VERSION>\n```\n\nMinimum TLS cipher suite (`minTlsCipherSuite`):\n\n```bash\naz functionapp update --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --set siteConfig.minTlsCipherSuite=\u003cMIN_TLS_CIPHER_SUITE>\n```\n\nHTTPS-only (`httpsOnly`):\n\n```bash\naz functionapp update --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --set httpsOnly=\u003ctrue|false>\n```\n\nClient certificate enabled (`clientCertEnabled`):\n\n```bash\naz functionapp update --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --set clientCertEnabled=\u003ctrue|false>\n```\n\nClient certificate mode (`clientCertMode`, one of `Required`, `Optional`, `OptionalInteractiveUser`):\n\n```bash\naz functionapp update --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --set clientCertMode=\u003cCLIENT_CERT_MODE>\n```\n\nClient certificate exclusion paths (`clientCertExclusionPaths`):\n\n```bash\naz functionapp update --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --set clientCertExclusionPaths=\u003cCLIENT_CERT_EXCLUSION_PATHS>\n```\n\nSCM basic publishing credentials policy (the `allow` value from Step 3a's `basicPublishingCredentialsPolicies` query):\n\n```bash\naz resource update --resource-group \u003cRESOURCE_GROUP> --name scm --namespace Microsoft.Web --resource-type basicPublishingCredentialsPolicies --parent sites/\u003cNEW_APP_NAME> --set properties.allow=\u003ctrue|false>\n```\n\n> ⚠️ **Skill instruction**: For each command above, look at the corresponding field from Step 3a's output. If the value was `null` or the field was absent, **skip that command** — do not pass `null` or an empty string. If all Step 3a site-config values were already at Flex defaults (typically `httpsOnly=true`, `minTlsVersion=1.2`, all others null/false), this entire sub-step is a no-op and may be skipped.\n\n### 4e. Migrate System-Assigned Managed Identity\n\nCheck if the source app has a system-assigned identity:\n\n```bash\naz functionapp identity show --name \u003cSOURCE_APP_NAME> --resource-group \u003cSOURCE_RESOURCE_GROUP> --query principalId -o tsv\n```\n\n> Only proceed with the rest of this step if the principal ID above is non-empty. Save it as `\u003cSOURCE_PRINCIPAL_ID>`.\n\nEnable system identity on the new app:\n\n```bash\naz functionapp identity assign --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP>\n```\n\nGet the new app's system identity principal ID (save it as `\u003cNEW_PRINCIPAL_ID>`):\n\n```bash\naz functionapp identity show --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --query principalId -o tsv\n```\n\nList the source app's role assignments — project just the fields needed to recreate them:\n\n```bash\naz role assignment list --assignee \u003cSOURCE_PRINCIPAL_ID> --all --query \"[].{role:roleDefinitionName, scope:scope}\" -o tsv\n```\n\n> ⚠️ **Skill instruction**: For **each row** above, run the command below — substitute the row's first column into `\u003cROLE_NAME>` and the row's second column into `\u003cRESOURCE_ID>`. The new SMI is a different principal than the source, so every assignment must be recreated explicitly; nothing carries over automatically. If 4b.opt already ran, the three storage data-plane roles on `\u003cSTORAGE_NAME>` are already assigned — skip those rows to avoid duplicates.\n>\n> Before recreating a role, determine whether its scope is a retained dependency or a resource replaced by the migration. Recreate retained dependency scopes directly. Do **not** grant the new identity access to the source Application Insights component; if the source uses AAD ingestion, Step [4k](trigger-safety-and-monitoring.md#4k-verify-application-insights-monitoring) grants `Monitoring Metrics Publisher` on the target component instead.\n>\n> ```bash\n> az role assignment create --assignee-object-id \u003cNEW_PRINCIPAL_ID> --assignee-principal-type ServicePrincipal --role \"\u003cROLE_NAME>\" --scope \"\u003cRESOURCE_ID>\"\n> ```\n\n### 4f. Migrate User-Assigned Managed Identities\n\nList user-assigned identities on the source app:\n\n```bash\naz functionapp identity show --name \u003cSOURCE_APP_NAME> --resource-group \u003cSOURCE_RESOURCE_GROUP> --query userAssignedIdentities -o json\n```\n\nAssign each identity to the new app (repeat per identity resource ID):\n\n```bash\naz functionapp identity assign --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --identities \u003cIDENTITY_RESOURCE_ID>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5102,"content_sha256":"fd59b6153ed7937e73de74829c2d19ed6080630068e078f569c3382a5e91275d"},{"filename":"references/services/functions/consumption-to-flex/windows/automation/trigger-safety-and-monitoring.md","content":"# Trigger Safety and Monitoring\n\n### 4j. Choose the Pre-Deployment State of Non-HTTP Functions\n\n> ⚠️ **Why this decision exists**: When Step 5 deploys code, enabled non-HTTP functions can immediately consume events or run schedules. The risk is highest when 4c copied production settings, 4b reused the source storage account (including implicit `AzureWebJobsStorage` bindings), or timer triggers are present. Disabling the target functions before deployment makes cutover controllable in Step 6.\n>\n> HTTP triggers are intentionally left enabled — they don't pull from a queue, so the new app cannot \"steal\" HTTP traffic. Clients must be redirected to the new hostname explicitly, which gives you the same safety as disabling.\n>\n> Reference: [Disable functions in Azure Functions](https://learn.microsoft.com/en-us/azure/azure-functions/disable-function).\n>\n> ⚠️ On Linux, a function whose name contains a hyphen (`-`) cannot be disabled through `AzureWebJobs.\u003cFUNCTION_NAME>.Disabled`. Never claim that this setting protects a hyphenated function on the Flex target.\n\nRead each deployed function's trigger binding from the ARM function metadata:\n\n```bash\naz functionapp function list --name \u003cSOURCE_APP_NAME> --resource-group \u003cSOURCE_RESOURCE_GROUP> --query \"[].{name:config.name,triggerType:(config.bindings[?ends_with(type, 'Trigger')] | [0].type)}\" -o table\n```\n\n> 💡 Use the alias `triggerType`, not `type`. Azure CLI's table formatter suppresses common resource metadata fields named `type`, which can make a valid projection appear blank.\n>\n> ⚠️ **Skill instruction**:\n>\n> 1. Reconcile the ARM results with the trigger inventory recorded in the assessment report.\n> 2. If ARM genuinely returns a blank, missing, or ambiguous trigger, use source attributes or `function.json` as the fallback.\n> 3. If a function remains unresolved, stop — never assume it is event-driven or HTTP.\n> 4. Confirm that every deployed function has exactly one classified trigger before presenting the disablement decision.\n> 5. Split non-HTTP functions into names that contain `-` and names that do not. Record both lists in `\u003cUPGRADE_DIR>/upgrade-status.md`.\n\nEvaluate these risk factors:\n\n- whether source app settings were copied in 4c;\n- whether the source storage account was reused in 4b;\n- whether timers or unresolved binding sources are present.\n\nIf there are no non-HTTP functions, mark Step 4j `skipped — no non-HTTP functions`. If settings were deferred, runtime storage and every trigger dependency are isolated from production, no timer or other autonomous function can affect production, and every binding source is resolved, mark Step 4j `skipped — target fully isolated`. In either case, do not present a disablement prompt or add per-function disable settings; record any hyphenated names and the Linux limitation, then continue to 4k.\n\nIf any production-connected non-HTTP function name contains `-`, do not attempt to disable it on the target. Use `ask_user` to list the affected functions, explain that they will be active when the Linux target starts, and offer these choices:\n\n1. **Isolate target dependencies (recommended)** — configure target-specific queues, topics, containers, consumer groups, event subscriptions, schedules, or other bindings, then reassess Step 4j.\n2. **Rename and repackage** — change the function names so setting-based disablement is supported, redeploy the source if required, and reassess.\n3. **Source-first deployment cutover** — immediately before Step 5, disable and verify the affected functions on the Windows source, deploy the target, and validate it. This can pause processing and backlog events. If deployment or validation fails, stop the entire target app before restoring the source functions.\n4. **Deploy active** — explicitly accept that the affected target functions can process production events or schedules as soon as deployment completes.\n\nRecord the selected path and affected function names in `\u003cUPGRADE_DIR>/upgrade-status.md`. Choices 1 and 2 block deployment until completed. Choice 3 is executed as the transaction in [Step 5](code-deployment.md#hyphenated-function-source-first-deployment-cutover). Choice 4 requires the same immediate pre-deployment warning and approval as declined disablement.\n\nFor the remaining non-HTTP functions whose names do not contain `-`, use `ask_user` to list them and summarize the observed risk factors. Strongly recommend disabling all listed functions when any risk factor is present, but leave the decision to the user. Record the choice in `\u003cUPGRADE_DIR>/upgrade-status.md`.\n\nIf the user approves, set a disable flag on the new app for every listed non-HTTP function whose name does not contain `-` (repeat per function name). Leave HTTP and hyphenated functions unchanged:\n\n```bash\naz functionapp config appsettings set --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --settings \"AzureWebJobs.\u003cFUNCTION_NAME>.Disabled=true\" --output none\n```\n\nThe runtime reads these settings at startup, so they are intended to take effect when Step 5 deploys code. Do not call the functions effectively disabled until their runtime state is verified after deployment.\n\nIf disablement was approved, verify that the settings were written before moving on:\n\n```bash\naz functionapp config appsettings list --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?starts_with(name, 'AzureWebJobs.') && ends_with(name, '.Disabled')].{name:name, value:value}\" -o table\n```\n\n> ⚠️ **Skill instruction**: If the user approves, apply one `--settings` call per function. Each call triggers a soft-restart but the underlying `Microsoft.Web/sites` PATCH has a payload limit, so batching dozens into one call can fail. If the source app has more than ~50 functions, write the disable settings to `\u003cUPGRADE_DIR>/disabled_functions.json` (e.g. `[{\"name\": \"AzureWebJobs.FuncA.Disabled\", \"value\": \"true\"}, ...]`) and apply via `--settings @\u003cUPGRADE_DIR>/disabled_functions.json` in a single call. Delete the file immediately after the apply succeeds (it does not contain secrets, but follow the [Artifact Output Policy](../../../../../global-rules.md#artifact-output-policy) for cleanup hygiene).\n>\n> If the user declines, or selects **Deploy active** for a hyphenated function, do not write a disable setting for the affected functions. Immediately before Step 5 deployment, use `ask_user` again to warn that the listed functions may consume shared events or run duplicate schedules as soon as deployment completes, then obtain explicit approval to deploy with them enabled.\n\n### 4k. Verify Application Insights Monitoring\n\nMicrosoft Learn requires monitoring to be enabled before deployment but does not require changing workspaces or authentication models during migration. Preserve the monitoring configuration created or verified by Step 4b unless the user explicitly requests customization.\n\nRestore `\u003cTARGET_AI_NAME>`, `\u003cTARGET_AI_RESOURCE_ID>`, and `\u003cTARGET_AI_RESOURCE_GROUP>` from the verified Step 4b metadata in progress Notes. Require the name and resource group to agree with the component resource ID. Missing or conflicting metadata is a blocker; do not infer the component's resource group from the function app. Address the component by its full resource ID below so lookups use its own subscription and resource group.\n\nThis step verifies that Application Insights is configured and authorized. It does not query telemetry or prove that logs are being ingested; validate runtime behavior and telemetry after code deployment.\n\nVerify the target has an Application Insights connection setting without displaying its value:\n\n```bash\naz functionapp config appsettings list --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?name=='APPLICATIONINSIGHTS_CONNECTION_STRING'].name\" -o tsv\n```\n\nVerify the Application Insights component recorded from Step 4b:\n\n```bash\naz monitor app-insights component show --ids \u003cTARGET_AI_RESOURCE_ID> --query \"{name:name,id:id,workspaceResourceId:workspaceResourceId}\" -o table\n```\n\nRequire the component lookup to succeed and its returned name and resource ID to match the recorded metadata. If either the setting or component is absent, the read fails, or metadata conflicts, stop and investigate. Use `ask_user` before creating or wiring a replacement monitoring resource. Do not change the selected Log Analytics workspace unless the user explicitly requests monitoring customization.\n\nCheck whether the source used AAD-authenticated ingestion:\n\n```bash\naz functionapp config appsettings list --name \u003cSOURCE_APP_NAME> --resource-group \u003cSOURCE_RESOURCE_GROUP> --query \"[?name=='APPLICATIONINSIGHTS_AUTHENTICATION_STRING'].value | [0]\" -o tsv\n```\n\n- If the value is not `Authorization=AAD`, keep the target's platform-created monitoring configuration unchanged. Offer AAD ingestion only as optional post-migration hardening.\n- If the value is `Authorization=AAD`, preserve that posture on the target:\n\n ```bash\n az functionapp config appsettings set --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --settings \"APPLICATIONINSIGHTS_AUTHENTICATION_STRING=Authorization=AAD\" --output none\n ```\n\n Use `\u003cNEW_PRINCIPAL_ID>` from 4e and grant it `Monitoring Metrics Publisher` on the **target** Application Insights component:\n\n ```bash\n az role assignment create --assignee-object-id \u003cNEW_PRINCIPAL_ID> --assignee-principal-type ServicePrincipal --role \"Monitoring Metrics Publisher\" --scope \u003cTARGET_AI_RESOURCE_ID>\n ```\n\nVerify setting names and the target-scoped role without displaying connection-string values:\n\n```bash\naz functionapp config appsettings list --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[?starts_with(name, 'APPLICATIONINSIGHTS_')].name\" -o tsv\n```\n\n```bash\naz role assignment list --assignee-object-id \u003cNEW_PRINCIPAL_ID> --scope \u003cTARGET_AI_RESOURCE_ID> --query \"[?roleDefinitionName=='Monitoring Metrics Publisher'].{role:roleDefinitionName,scope:scope}\" -o table\n```\n\n### Verify Migration Results\n\nVerify the new app exists and is configured:\n\n```bash\naz functionapp show --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"{name:name, kind:kind, sku:properties.sku}\" --output table\n```\n\nReview target app-setting names:\n\n```bash\naz functionapp config appsettings list --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --query \"[].name\" -o tsv\n```\n\nCheck managed identity:\n\n```bash\naz functionapp identity show --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP>\n```\n\nCheck custom domains:\n\n```bash\naz functionapp config hostname list --webapp-name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --output table\n```\n\n### Configure Items Requiring Manual Setup\n\nThese are not handled by Steps 4a–4i and require manual configuration:\n\n#### TLS/SSL Certificates\n\nIf Step 2e identified certificates used by the source app, re-add only those certificates using the documented [site-scoped certificate process](https://learn.microsoft.com/en-us/azure/azure-functions/flex-consumption-how-to#configure-site-scoped-certificates). Confirm the target remains within the limit of three private and three public certificates.\n\n`WEBSITE_LOAD_CERTIFICATES` is not used by Flex Consumption. Make each required certificate accessible to app code through the documented process, and update code that used the Windows certificate store to load from `/var/ssl/certs` for public certificates or `/var/ssl/private` for private certificates.\n\n#### Scale and Concurrency (if custom values needed)\n\nUse the `WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT` value collected in [Step 3a](configuration-inventory.md#3a-collect-application-configurations) as `\u003cMAX_SCALE_SETTING>`. If the source setting was absent, keep the target default and skip this command. If it was set, confirm the value is within the Flex Consumption range of 1–1000 before applying it:\n\n```bash\naz functionapp scale config set --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --maximum-instance-count \u003cMAX_SCALE_SETTING>\n```\n\n> ⚠️ Reducing below 40 for HTTP apps can cause frequent request failures.\n\n---\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":12119,"content_sha256":"96a273c12d503d8cfeb5b73882bd3ed87180a686103b2def6e4799c291b09107"},{"filename":"references/services/functions/consumption-to-flex/windows/automation/validation-and-cutover.md","content":"# Validation and Cutover\n\n## Step 6: Post-Upgrade Validation\n\nEnter Step 6 only after Step 5a is complete or skipped because target-generated keys were selected. If key preservation was selected but any host or HTTP-function key failed verification, stop.\n\n### Confirm the source app is still healthy\n\nBefore touching the new app, verify the source is still serving traffic and processing events as expected. The cutover that follows assumes the source remains the system of record until each trigger is flipped over individually.\n\n```bash\naz functionapp show --name \u003cSOURCE_APP_NAME> --resource-group \u003cSOURCE_RESOURCE_GROUP> --query \"{name:name, state:state, hostNames:hostNames[0]}\" -o table\n```\n\nExpected: `state` is `Running`. If anything looks off (state is `Stopped`, hostname is null, etc.), pause the cutover and investigate before proceeding — the cleanup steps later in this phase assume the source app is healthy.\n\n### Smoke Test (run this first)\n\nGet the new app's default hostname:\n\n```bash\naz functionapp show --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --query defaultHostName -o tsv\n```\n\n> ⚠️ **Flex propagation**: On a freshly-created Flex Consumption app, `defaultHostName` from `az functionapp show` can briefly return null while the platform finishes provisioning. If the command above returns empty, fall back to:\n>\n> ```bash\n> az functionapp list --resource-group \u003cRESOURCE_GROUP> --query \"[?name=='\u003cNEW_APP_NAME>'].defaultHostName | [0]\" -o tsv\n> ```\n>\n> The list endpoint populates the field as soon as the app exists.\n\nConfirm the host is reachable (substitute `\u003cHOSTNAME>` with the value above):\n\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" \"https://\u003cHOSTNAME>\"\n```\n\nExpected: a 2xx, 401, or 404 (the host is up). If the response is `403 Ip Forbidden` and the target has an intentional deny-by-default policy, record the HTTP smoke test as deferred until it can run from an already allowed client. Confirm the app and functions through the ARM commands from Step 5; do not add or relax access rules automatically.\n\nIf you get 503 or a connection refusal, the app failed to start — check logs:\n\n```bash\naz functionapp log tail --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP>\n```\n\n> 💡 On PowerShell 7+, `curl` resolves to the real `curl.exe` (the legacy `Invoke-WebRequest` alias was removed in 7.x). Confirm with `Get-Command curl` if unsure.\n\n### Verify Plan\n\n```bash\naz functionapp show --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --query serverFarmId\n```\n\n### Test HTTP Endpoints\n\nTest an individual HTTP trigger (substitute `\u003cHOSTNAME>` and `\u003cFUNCTION_NAME>`):\n\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" \"https://\u003cHOSTNAME>/api/\u003cFUNCTION_NAME>\"\n```\n\nFor a function that requires a function or host key, use the selected target key in the `x-functions-key` header without printing or persisting it. If target-generated keys were selected, don't treat HTTP cutover as complete until every key-dependent client or workflow has been updated and validated.\n\n### Validate Built-in Authentication\n\nStep 4f.auth must be complete or skipped because source Easy Auth was disabled before entering Step 6. If it is deferred or blocked, do not deploy code or run target HTTP checks.\n\nIf Step 4f.auth was completed, test an endpoint that requires authentication and confirm its anonymous behavior matches the verified target configuration: `401`/`403` for rejection or the expected provider redirect. Then complete one authenticated request using a test identity and confirm the expected authorization result without recording tokens.\n\n### Per-Function Cutover (event-driven triggers)\n\nFor non-hyphenated functions effectively disabled and verified after Step 5, handle them one at a time. Never enable a production-connected target function before approval to disable its source counterpart; otherwise both apps can process the same event source while approval is pending. If Step 4j disablement was declined, report that controlled cutover protection was not established and validate for concurrent processing before any source change.\n\nDo not use the target app-setting disable/enable transaction below for a function whose name contains `-`; Linux does not support disabling that name through `AzureWebJobs.\u003cFUNCTION_NAME>.Disabled`. Use isolated target dependencies or the source-first deployment cutover recorded in Step 4j. If a hyphenated function was deployed active with explicit approval, validate for concurrent processing and do not claim controlled per-function cutover.\n\n> ⚠️ **Per-trigger mitigations apply first**: Even with this controlled per-function cutover, the [Trigger Migration Risks](../workflow.md#trigger-migration-risks) table lists per-trigger-type prerequisites — new consumer group for Event Hubs, dedicated lease container for Cosmos DB, new event subscription for blob/EventGrid, etc. Apply the relevant mitigation **before** flipping the disable flag for the corresponding function.\n\nFor Blob/Event Grid triggers, check that the target's current networking configuration still permits the agreed inbound delivery path before enabling the target. Do not generate test events, create test blobs, or provision test resources for these triggers. Configuration checks, a healthy HTTP endpoint, and a successfully created event subscription do not prove runtime delivery. Use existing execution telemetry or user-provided validation evidence; otherwise report runtime delivery as unverified and leave trigger validation incomplete. Do not relax network restrictions automatically.\n\nFor each event-driven function, choose one of these paths:\n\n#### Path A: Isolated Target Validation\n\nPoint the target binding at an isolated test queue, consumer group, lease container, event subscription, or equivalent resource. For a non-hyphenated function, enable and validate the target, then disable it again until production cutover is approved. A hyphenated function is already active after deployment; validate it only against isolated dependencies and do not restore its production binding until the transaction below is approved.\n\n#### Hyphenated-Function Production Cutover\n\nFor a hyphenated function already validated against isolated dependencies, use `ask_user` for a transaction that:\n\n1. Stops the entire target app and verifies it is stopped.\n2. Disables the corresponding function on the Windows source and verifies `isDisabled=true`.\n3. Replaces the target's isolated binding configuration with the production configuration.\n4. Starts the target app and validates one normal execution cycle.\n5. On failure, stops the target, restores its isolated binding configuration, re-enables and verifies the source function, and reports the failure.\n\nExplain that stopping the Flex app affects every target function and that events may backlog during this transaction. Approval applies only to the named function, binding changes, and this cutover attempt.\n\n#### Path B: Production Cutover\n\nUse this path only for target function names that do not contain `-`.\n\n1. Use `ask_user` **before enabling the target or changing the source**. Request approval for the complete function-specific transaction, including conditional rollback:\n\n > May I cut over `\u003cFUNCTION_NAME>` by disabling it on source app `\u003cSOURCE_APP_NAME>`, verifying the source is disabled, and then enabling it on target app `\u003cNEW_APP_NAME>`? This may briefly pause processing and allow events to backlog. If target activation or validation fails, I will disable the target and restore the source function. This approval applies only to this function and this cutover attempt.\n\n Do not continue unless the user approves. If approval is declined, leave the source enabled and target disabled. Approval for one function does not cover another function or a later retry.\n\n2. Disable the source function and suppress command output because app-setting responses can contain secrets:\n\n ```bash\n az functionapp config appsettings set --name \u003cSOURCE_APP_NAME> --resource-group \u003cSOURCE_RESOURCE_GROUP> --settings \"AzureWebJobs.\u003cFUNCTION_NAME>.Disabled=true\" --output none\n ```\n\n3. Verify the source reports the function as disabled before enabling the target:\n\n ```bash\n az functionapp function list --name \u003cSOURCE_APP_NAME> --resource-group \u003cSOURCE_RESOURCE_GROUP> --query \"[?config.name=='\u003cFUNCTION_NAME>'].{name:config.name,disabled:isDisabled}\" -o table\n ```\n\n4. Enable the target:\n\n ```bash\n az functionapp config appsettings set --name \u003cNEW_APP_NAME> --resource-group \u003cRESOURCE_GROUP> --settings \"AzureWebJobs.\u003cFUNCTION_NAME>.Disabled=false\" --output none\n ```\n\n5. Verify target processing after one full execution cycle or controlled test event:\n\n ```kql\n requests\n | where cloud_RoleName == \"\u003cNEW_APP_NAME>\"\n | where operation_Name == \"\u003cFUNCTION_NAME>\"\n | where timestamp > ago(15m)\n | summarize count(), avg(duration), countif(success == false) by bin(timestamp, 1m)\n ```\n\n6. If target activation or validation fails, use the rollback authorized in step 1: disable and verify the target first, then re-enable and verify the source. Report the failure and obtain new approval before another cutover attempt.\n\n> ⚠️ **Pause versus duplication**: Source-first cutover can briefly delay processing or miss a timer occurrence, but queued/event-stream work normally remains available as backlog. This is safer than enabling both production-connected functions concurrently, which can cause duplicate or competing processing.\n\n### Performance Benchmarks (Application Insights KQL)\n\n```kql\nrequests\n| where timestamp > ago(1d)\n| summarize percentiles(duration, 50, 95, 99) by bin(timestamp, 1h)\n| render timechart\n```\n\n### Check for Errors\n\n```kql\ntraces\n| where severityLevel == 3\n| where cloud_RoleName == \"\u003cNEW_APP_NAME>\"\n| where timestamp > ago(1d)\n| project timestamp, message, operation_Name, customDimensions\n| order by timestamp desc\n```\n\n---\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9944,"content_sha256":"d0fb5c209db57f409224ca91b915afbb23840b78d0dec0e32e4d5fe9e84b889f"},{"filename":"references/services/functions/consumption-to-flex/windows/dependency-scan.md","content":"# Source Code Windows Dependency Scan\n\n> **When**: Phase 1 Assessment, after [Step 2f](automation/discovery-and-assessment.md#2f-check-blob-storage-triggers), as **[Step 2g](automation/discovery-and-assessment.md#2g-source-code-windows-dependency-scan)**. **Always recommended, never required.** If the user skips, proceed — they own the runtime risk.\n\n## What This Scan Does\n\nWalks the source tree for code, config, and packaging patterns that depend on Windows. Prefer source code because project manifests and API usage are directly inspectable. Use the deployed package from [Step 3e](automation/deployment-package.md#3e-get-deployment-package-if-needed) only when source is unavailable; it confirms what is running but may contain compiled artifacts that reduce scan coverage. Findings populate **§11** of the assessment report; ≥1 `Blocker` finding advisorily flips **§1 Upgrade Readiness** to `Needs Attention` (never hard-blocks).\n\n> ⚠️ **Heuristic aid, not a guarantee.** This scan pattern-matches the most common Windows-only APIs, packages, RID targeting, and shell-outs to Windows tools. It is **not exhaustive** — uncommon Windows APIs, dynamically-loaded DLLs, transitive package dependencies, reflection-based calls, and runtime-generated code can slip past. **The app owner is ultimately responsible for verifying their code has no Windows dependencies.** False negatives are dangerous; false positives create friction. The scan's job is to **inform**, not gate.\n\n## Inputs\n\n1. **Source location** — use `ask_user` to explicitly request a local source directory or checked-out repository path; do not infer that the current workspace contains the function app. Explain that source provides the best scan coverage. If the user cannot provide source, offer the deployed package from Step 3e as a fallback. If they decline both, write \"scan skipped\" to §11 and stop.\n2. **Language** — auto-dispatched from `FUNCTIONS_WORKER_RUNTIME` (captured in [Step 2b](automation/discovery-and-assessment.md#2b-verify-language-stack-compatibility)). Always run the agnostic set + the matching per-language set.\n3. **`custom` worker** — agnostic set only; ask once if the handler is C#, Node, Java, Python, or PowerShell source and layer in that set if so.\n\n## Categories\n\n| # | Category |\n|---|----------|\n| 1 | Win32 / WinRT / COM / WMI APIs |\n| 2 | Path / case / line-ending / env-var assumptions |\n| 3 | Windows certificate store |\n| 4 | Windows registry |\n| 5 | Windows-only packages |\n| 6 | Windows-RID / `net4x` targeting |\n| 7 | Windows-only PowerShell modules |\n| 8 | Shelling out to Windows tools |\n\n## Finding Severity\n\n| Severity | Meaning | Effect on §1 |\n|----------|---------|-------------|\n| 🛑 **Blocker** | Will definitely fail on Linux (e.g. `[DllImport(\"kernel32.dll\")]`, `Microsoft.Win32.Registry`, `System.Drawing.Common` on .NET 6+, `.exe` handler for `custom` worker) | `Needs Attention` (advisory) |\n| ⚠️ **Likely** | Often breaks but may be guarded (backslash paths, drive letters, RID-specific package refs) | None |\n| ℹ️ **Review** | Heuristic worth a human eye (any P/Invoke, any external `Process.Start`, package name containing `Windows`) | None |\n\n## How to Read These Patterns\n\nEach bullet below states a **principle** followed by anchor examples. Treat the examples as starting points, not as an exhaustive whitelist — when you encounter similar patterns that aren't enumerated (a different system DLL, a different `System.*` namespace prefix, a different Windows admin exe, a different Windows-only PowerShell module, a different `win32`-flavored npm package name), flag them under the same category. The category headers in **bold** are the rule; the examples after the em-dash are how that rule commonly shows up.\n\n## Language-Agnostic Patterns\n\nRun for every worker runtime. Cite the category number on each finding.\n\n- **(2) Windows path / env-var literals** — path-like strings with a drive letter (`@\"C:\\...\"`, `\"D:\\\\...\"`) or Windows env-var references in the `%FOO%` shape (`%TEMP%`, `%USERPROFILE%`, `%WINDIR%`, `%PROGRAMFILES%`, `%APPDATA%`, `%LOCALAPPDATA%`, …).\n- **(2) CRLF-dependent parsing** — `Split(\"\\r\\n\")`, byte-exact file reads, anything that hard-codes `\\r\\n` line endings.\n- **(8) Spawning a Windows-only executable** — language-specific syntax varies (see per-language), but the executable is one of: `cmd`, `powershell`/`pwsh`, `cscript`, `wscript`, `reg`, `wmic`, `tasklist`, `net`, `sc`, `iisreset`, `netsh`, `wevtutil`, or any path ending `.exe`/`.bat`/`.cmd`/`.ps1`.\n- **(8) Windows device / pipe paths** — paths starting with `\\\\.\\` (devices, named pipes), `\\\\?\\` (Win32 long-path namespace), or `\\\\.\\pipe\\` specifically. No Linux equivalent.\n- **(6) Windows-RID in build/deploy config** — `.csproj`/`.fsproj`/`launchSettings.json`/`Dockerfile`/pipeline yaml referencing `win-x64`, `win-x86`, `win-arm64`, or `win10-*` outside a Windows-only condition.\n- **(6) Windows-only `runtimes/win-*/` payload** — deployment package contains `runtimes/win-*/` without a matching `runtimes/linux-x64/`.\n\n## Per-Language Patterns\n\n### `dotnet-isolated`\n\n- **(1) Win32 P/Invoke** — `[DllImport(\"\u003cdll>\")]` of any Windows system DLL: `kernel32`, `user32`, `advapi32`, `ole32`, `gdi32`, `shell32`, `ntdll`, `wininet`, `crypt32`, etc.\n- **(1) Windows-only .NET namespaces** — `using` directives, fully-qualified type names, or `PackageReference` whose namespace prefix exists only to wrap Windows. Match the **prefix**, not the leaf type. Known prefixes: `System.Drawing.*` (GDI+), `System.DirectoryServices.*` (ADSI/LDAP), `System.Management.*` (WMI), `Microsoft.Win32.*` (registry, scheduler), `System.ServiceProcess.*` (Windows services), `Microsoft.Office.Interop.*`.\n- **(1) COM activation** — `[ComImport]`, `Marshal.GetActiveObject`, `Type.GetTypeFromProgID` / `…FromCLSID`, `Activator.CreateInstance` of a COM type, or string-literal ProgIDs (`WScript.Shell`, `Excel.Application`, `Word.Application`, …).\n- **(3) Windows certificate store** — `X509Store(StoreLocation.LocalMachine | CurrentUser)`. Linux uses an OpenSSL-backed store; behavior differs even where the API exists.\n- **(4) Windows registry** — anything under `Microsoft.Win32.Registry*` (`Registry.LocalMachine`, `Registry.CurrentUser`, `Registry.ClassesRoot`, `RegistryKey.*`).\n- **(5) Windows-only NuGet packages** — `\u003cPackageReference>` id matching `*Windows*`, `*.Win32*`, or `*.Office.Interop.*`. Specific offenders: `System.Drawing.Common`, `System.Management`, `System.DirectoryServices.AccountManagement`, `Microsoft.Windows.Compatibility`, `WindowsAzure.Storage`.\n- **(6) Windows-RID targeting** — `\u003cRuntimeIdentifier>` / `\u003cRuntimeIdentifiers>` containing any `win-*` (`win-x64`, `win-x86`, `win-arm64`, `win10-*`) without a matching `linux-*`.\n- **(6) `net4x` target framework** — `\u003cTargetFramework[s]>` containing `net4` (also in [Known Limitations](workflow.md#known-limitations-and-migration-blockers)).\n- **(8) Shelling out to a Windows-only tool** — `Process.Start(...)` / `new ProcessStartInfo(...)` whose executable matches the agnostic Windows-tool list.\n\n### `node`\n\n- **(1) Windows-only npm packages** — `require`/`import` of packages whose purpose is wrapping Windows. Naming patterns: `node-windows-*`, `windows-*`, `win32-*`. Known: `node-windows`, `windows-shortcuts`, `windows-foreground-love`, `node-task-scheduler`, `edge`/`edge-js` (CLR bridge), `regedit`.\n- **(5) Windows-only npm dependencies** — `package.json` deps matching the naming patterns above, or `os: [\"win32\"]` (refuses to install on Linux), or `cpu` constraints excluding Linux arches.\n- **(6) Pre-built Windows native add-ons** — `node_modules/**/*.node` files that are PE-format. Any `.node` shipped without a Linux-built equivalent fails to load. Solution: rebuild on Linux at deploy time.\n- **(8) Shelling out to a Windows-only tool** — `child_process.exec`/`spawn`/`execSync` whose command matches the agnostic Windows-tool list.\n\n### `java`\n\n- **(1) Windows-only Java APIs** — `import` of namespaces wrapping Windows: `com.sun.jna.platform.win32.*`, `com.jacob.*` (COM bridge), `org.eclipse.swt.win32.*`, anything ending in `.win32`. Also flag `System.loadLibrary` / `System.load` whose argument resolves to a `.dll`.\n- **(5) Windows-only Maven/Gradle deps** — `pom.xml` / `build.gradle` entries whose `groupId:artifactId` contains `windows`, `win32`, or `jacob`. Anchors: `com.sun.jna:jna-platform`, `net.sf.jacob-project:jacob`, `org.eclipse.swt.win32.*`.\n- **(6) Bundled Windows native binaries** — `.dll` files under `src/main/resources/`, `META-INF/native/`, or shaded into the jar — won't load on Linux even if the calling Java is portable.\n- **(8) Shelling out to a Windows-only tool** — `Runtime.exec(...)` / `new ProcessBuilder(...)` whose command matches the agnostic Windows-tool list.\n\n### `python`\n\n- **(1) Windows-only Python modules** — `import` of any module in the `win32*` family (`win32api`, `win32com`, `win32con`, `win32event`, `win32file`, `win32process`, `win32security`, …), the registry interfaces (`winreg`, `_winreg`), or COM/WMI bridges (`pythoncom`, `wmi`, `pywinauto`, `comtypes`, `pythonnet`).\n- **(1) Win32 via ctypes** — `ctypes.windll.*`, `ctypes.WinDLL(...)`, `ctypes.OleDLL(...)`. The `ctypes.windll` attribute itself only exists on Windows Python.\n- **(5) Windows-only pip dependencies** — `requirements.txt` / `pyproject.toml` / `Pipfile` entries whose name signals Windows-only (`pywin32`, `pywinauto`, `wmi`, `winshell`, `pythonnet`, `comtypes`, `win32-*`) or pinned via `sys_platform == 'win32'` environment marker without an alternate branch.\n- **(8) Shelling out to a Windows-only tool** — `subprocess.run`/`Popen`/`call` or `os.system` whose command matches the agnostic Windows-tool list.\n\n### `powershell`\n\n**Flex Consumption packaging check:** Inspect `host.json`, `requirements.psd1`, and the app-root `Modules` folder to determine whether the app relies on managed dependencies. Flex Consumption doesn't support managed dependencies, even for Linux-compatible modules. If required modules aren't bundled with the app, record that preparation is required in assessment report §11 and advise packaging them in `Modules` before deployment. Verify that the deployment package includes the required modules and their dependencies. Any source or packaging changes require user approval.\n\n- **(1, 7) WMI / CIM cmdlets** — `Get-WmiObject`, `Get-CimInstance`, `Invoke-WmiMethod`, `Invoke-CimMethod`. PowerShell 7 on Linux silently returns `null` instead of erroring — failures are easy to miss.\n- **(1) COM activation & Windows-only providers** — `New-Object -ComObject …`, `Get-EventLog`, Windows-service form of `Get-Service`/`*-Service`, anything in `Microsoft.PowerShell.LocalAccounts`.\n- **(4, 7) Registry cmdlets / provider paths** — any access to the `Registry::` provider: `Get-ItemProperty Registry::*`, `Get-ChildItem HKLM:` / `HKCU:` / `HKCR:`, `Set-ItemProperty -Path HKLM:\\…`, `New-PSDrive -PSProvider Registry`.\n- **(7) Windows-only modules** — `Import-Module` of modules shipped only with Windows PowerShell, RSAT, or a Windows feature. Anchors: `ActiveDirectory`, `GroupPolicy`, `ServerManager`, `Hyper-V`, `BitsTransfer`, `ScheduledTasks`, `MSOnline`, `AzureAD`, `Dism`.\n- **(3) Windows certificate store** — paths under `Cert:\\LocalMachine\\*` or `Cert:\\CurrentUser\\*`. Linux PowerShell has a limited read-only implementation.\n- **(7) `requirements.psd1` `RequiredModules`** — pinning any module above.\n- **(8) Shelling out to a Windows-only tool** — `& cmd.exe …`, `Start-Process` of a Windows binary, `Invoke-Expression` of any Windows admin command line.\n\n### `go`\n\n- **(1) Windows-only Go APIs** — imports of `golang.org/x/sys/windows` or calls to `syscall.NewLazyDLL`, `windows.NewLazySystemDLL`, or other Windows DLL-loading APIs.\n- **(5, 6) Windows-only build constraints** — required source files named `*_windows.go`, `//go:build windows` constraints without a Linux implementation, or build/deployment configuration that sets `GOOS=windows`.\n- **(6) Windows handler binaries** — deployed `.exe` or PE-format handler binaries without a Linux ELF equivalent.\n- **(8) Shelling out to a Windows-only tool** — `os/exec.Command` or `CommandContext` whose executable matches the agnostic Windows-tool list.\n\n### `custom`\n\nRun the agnostic set, plus:\n\n- **(6) Handler binary is a Windows PE** — `file \u003chandler>` reports `PE32+ executable … for MS Windows` → 🛑 Blocker (must be rebuilt for Linux).\n- **(6) Bundled Windows native deps** — `.dll` files in the package without matching `.so` / Linux ELF.\n- **(8) Windows-script handler entry-point** — `host.json` `customHandler.description.defaultExecutablePath` ending in `.exe`, `.bat`, `.cmd`, or `.ps1`.\n\nIf the user identifies the handler's source language as one of the supported seven, also layer in that set.\n\n## Output\n\nEach finding:\n\n```yaml\n- category: 1-8\n severity: blocker | likely | review\n file: \u003crelative path>\n line: \u003cline number, if applicable>\n match: \u003cthe matched code or setting>\n remediation: \u003cone-line fix or \"Migrate to Elastic Premium on Windows\">\n```\n\nFindings populate **§11 Source Code Windows Dependency Scan** of the assessment report — see the template in [assessment.md](assessment.md#assessment-report-format). If the user declined the scan, write *\"User declined the source code dependency scan. Migration proceeded without static analysis of Windows dependencies.\"* in place of the findings table.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":13603,"content_sha256":"cc452b3be73cc3684dfb345046c5ac443b800efe887dda0e855fca56a307f5a6"},{"filename":"references/services/functions/consumption-to-flex/windows/progress-tracking.md","content":"# Migration Progress\n\nMaintain `\u003cUPGRADE_DIR>/upgrade-status.md` and show the current status in chat at every transition. The workflow documents are the source of truth; do not maintain a second hard-coded step inventory here.\n\n## Build the Checklist\n\n1. Read the ordered `### Phase` headings in [workflow.md](workflow.md) to determine the phase names and total.\n2. Read the ordered workflow-unit table in [automation.md](automation.md). For each phase, load the linked automation files that own its work and add their executable headings in document order. Include conditional and optional headings; mark them skipped only after evaluating their conditions.\n3. Use a numbered step label such as `4g` as its stable ID. For unnumbered work, use the exact heading text.\n4. On resume, rebuild the workflow snapshot from the current headings and reconcile it with saved state:\n - preserve matching completed, skipped, deferred, blocked, and pending entries;\n - add new headings as pending in document order;\n - record renamed or removed saved entries under Notes instead of silently discarding them.\n\n## Resume After External Provisioning\n\nWhen Step 4b is blocked on keyless provisioning and the user returns with a target resource ID, load [Adopt a User-Provisioned Target](automation/app-creation.md#adopt-a-user-provisioned-target) before any target writes. Keep the block until read-only verification and user approval succeed. Do not reapply target-name defaults or rerun creation/conversion commands.\n\nRecord the adopted target resource ID in `Current Status` and its verified storage, identity, and monitoring resource IDs in Notes. Mark Step 4b complete only as externally provisioned and verified; reconcile applicable skipped steps as directed by the adoption procedure. Set `Next action` to the first unfinished step at or after 4c, not app creation. Preserve all outstanding approval gates.\n\n## Reporting Rules\n\n1. Before each action, update `Current Status` and display: `Phase \u003ccurrent> of \u003ctotal> · \u003cstep> · \u003cdescription> · \u003cstate>`.\n2. After success, mark the item complete and immediately display the next item.\n3. At an approval gate, use state `awaiting approval` and invoke `ask_user` in the same turn.\n4. Mark work `skipped — \u003creason>` when it is not applicable or the user intentionally omits it and no later action is expected in this migration.\n5. Mark work `deferred — \u003creason>` when it remains outstanding but the user chooses to continue, such as access-restricted HTTP validation or production trigger cutover. Preserve it in the workflow snapshot and summarize it in `Next action` or `Notes`; never represent it as complete.\n6. Mark work `blocked` when an intended action cannot proceed because of an error or unresolved dependency. Record the error without secrets and do not advance unless the user explicitly chooses to defer or skip the work.\n7. The workflow may advance past skipped or deferred items. A phase may close with those states, but its summary must identify deferred work.\n8. Do not report a percentage; validation and cutover duration varies by function count.\n\n## Migration Outcomes\n\nTrack an outcome separately from the current step state:\n\n| Outcome | Meaning |\n|---------|---------|\n| `in progress` | The workflow is still executing or awaiting decisions |\n| `validation-only success` | The target was created, configured, deployed, and verified at the agreed scope, but applicable production traffic or trigger cutover remains skipped or deferred |\n| `production cutover complete` | All applicable production traffic and triggers use the target, target processing is validated, no production-readiness work remains deferred, and the source no longer processes production workloads |\n| `rolled back` | The target migration was abandoned or reversed and the source remains the production app |\n\nNever infer `production cutover complete` from successful resource creation, deployment, ARM health, or partial validation alone. A user may explicitly conclude a test migration as `validation-only success`.\n\nState meanings:\n\n| State | Meaning |\n|-------|---------|\n| `pending` | Not started |\n| `in progress` | Currently executing |\n| `awaiting approval` | Waiting at an explicit user decision gate |\n| `blocked` | Intended work cannot proceed |\n| `skipped` | Not applicable or intentionally omitted; no later action expected |\n| `deferred` | Postponed and still outstanding |\n| `complete` | Finished and verified |\n\n## Status Template\n\n```markdown\n# Windows Consumption to Flex Migration Status\n\n## Current Status\n\n| Property | Value |\n|----------|-------|\n| Source app | \u003cSOURCE_APP_NAME> |\n| Target app | \u003cNEW_APP_NAME or pending> |\n| Target resource ID | \u003cverified target resource ID or pending> |\n| Outcome | in progress / validation-only success / production cutover complete / rolled back |\n| Current phase | \u003ccurrent> of \u003ctotal derived from scenario headings> |\n| Current step | \u003cstep> |\n| State | pending / in progress / awaiting approval / blocked / skipped / deferred / complete |\n| Next action | \u003cdescription> |\n| Last updated | \u003cUTC timestamp> |\n\n## Workflow Snapshot\n\n\u003cPopulate from the current scenario and automation headings. Nest each phase's executable steps beneath it.>\n\n## Notes\n\n\u003cDecisions, skipped steps, failures, workflow reconciliation, and resumability details. Never record secrets.>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5371,"content_sha256":"d141b96984e7f70f400bf5dc2c8e855f54132f47784817c3592e43b51cb1de57"},{"filename":"references/services/functions/consumption-to-flex/windows/workflow.md","content":"# Windows Consumption Plan to Flex Consumption Plan Upgrade\n\n> **Source**: Azure Functions Consumption Plan (Y1/Dynamic) on Windows\n> **Target**: Azure Functions Flex Consumption Plan (FC1/FlexConsumption)\n> **Platform**: Windows → Linux (Flex Consumption is Linux-based)\n> **Docs**: [Windows migration guide](https://learn.microsoft.com/en-us/azure/azure-functions/migration/migrate-plan-consumption-to-flex?pivots=platform-windows)\n\n> ⚠️ **This is a Windows-to-Linux migration**, not just a plan change. Flex Consumption is Linux-based. Apps with Windows-specific dependencies, in-process .NET, .NET Framework targeting, or Windows-RID deployment packages must be prepared before migration. See [Known Limitations and Migration Blockers](#known-limitations-and-migration-blockers).\n\n## Before You Begin\n\nBefore running any discovery or Azure command, read the ordered `### Phase` headings in this workflow and the ordered workflow-unit table in [automation.md](automation.md). Present a concise user-facing summary in that order, combining implementation units under their corresponding phases. Do not maintain or infer a separate hard-coded step list.\n\nState that the source app remains read-only during assessment and replication. Every source-changing cutover, rollback, or cleanup action requires a separate, immediate approval. After presenting the plan, confirm the source app and Flex Consumption target plan with the user before continuing.\n\n## Why Upgrade?\n\n- **Faster cold starts** — always-ready instances mean functions respond more quickly\n- **Better scaling** — per-function scaling and concurrency controls\n- **Virtual network support** — connect to private networks and use private endpoints\n- **Active investment** — Flex Consumption is where new features land first\n\n## What to Expect\n\n1. **Your code may need changes** — unlike the Linux Consumption → Flex migration, this is a Windows-to-Linux OS change. Apps with Windows-only NuGet packages, P/Invoke, COM interop, .NET Framework dependencies, Windows-RID deployment packages, or Windows-specific PowerShell modules require preparation.\n2. **Create a new Flex app alongside the existing one** — test thoroughly on the new app before cutting over. This 2-app approach lets you discover Linux compatibility issues safely before committing.\n3. The new app runs in the **same resource group** with access to the same dependencies.\n4. **Deployment model changes** — Windows Consumption stores code on Azure Files (SMB); Flex uses immutable blob packages via One Deploy. Existing MSDeploy, FTP, and Kudu git push pipelines will not work after migration.\n5. You **control the timing** — the original Windows app stays running until you are confident in the migrated app.\n\n### Source-App Safety\n\nThe source app is read-only throughout assessment and replication. Before any cutover, rollback, or cleanup command that changes the source app's settings, triggers, state, deployment, bindings, or existence, the skill must use `ask_user` to describe the exact action and obtain explicit approval. Approval is specific to that action and cannot be reused for later source changes.\n\n## Platform Notes\n\n- **Recommended plan**: Flex Consumption is the recommended serverless hosting plan for Azure Functions. Do not assume or state a Windows Consumption retirement date unless current Microsoft documentation publishes one.\n- **OS change**: Flex Consumption is **Linux-based**. Windows-compiled binaries, Windows-only NuGet packages, COM interop, P/Invoke to Windows APIs, and Windows PowerShell modules will not run without modification.\n- **Deployment model**: Windows Consumption uses Azure Files (SMB share via `WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`/`WEBSITE_CONTENTSHARE`); Flex uses blob-based One Deploy (immutable zip packages in Azure Blob Storage).\n- **`az functionapp flex-migration` does not support Windows** — all migration steps use raw CLI commands (see [automation.md](automation.md)).\n- **Elastic Premium alternative**: Apps with hard Windows dependencies that cannot be removed can migrate to [Elastic Premium on Windows](https://learn.microsoft.com/en-us/azure/azure-functions/functions-premium-plan) instead of Flex Consumption. This is more expensive but changes the hosting plan without requiring an OS migration.\n\n## Prerequisites\n\n- Azure CLI v2.77.0+\n- `resource-graph` extension: `az extension add --name resource-graph`\n- `jq` tool for JSON processing\n- Owner or Contributor role in the resource group\n- Permissions to create and manage function apps, storage accounts, App Insights resources, and managed identity role assignments\n\n## Compatibility Requirements\n\n### Supported Language Stacks\n\n| Stack ID | Language | Supported? |\n|----------|----------|------------|\n| `dotnet-isolated` (.NET 8+) | .NET isolated worker, .NET 8+ | ✅ Yes — if no Windows-only dependencies and not published with a Windows RID |\n| `dotnet-isolated` (.NET Framework) | .NET isolated worker targeting `net4x` | ❌ No — .NET Framework runtime not present on Linux; must retarget to .NET 8+ |\n| `dotnet` | .NET in-process model | ❌ No — not supported on Flex; must migrate to isolated worker model first |\n| `node` | JavaScript/TypeScript | ✅ Yes |\n| `java` | Java | ✅ Yes |\n| `python` | Python | ✅ Yes |\n| `powershell` | PowerShell | ⚠️ Review — Windows-only modules (WMI, registry, COM interop) will not work on Linux |\n| `go` | Go (Preview) | ✅ Yes — if the handler and native dependencies are built for Linux |\n| `custom` | Custom handlers | ⚠️ Review — handler binary must be Linux-compatible |\n\n### Known Limitations and Migration Blockers\n\n#### Flex Consumption Platform Limits (shared with Linux migration)\n\n| Feature | Status | Action Required |\n|---------|--------|-----------------|\n| Deployment slots | ❌ Not supported | Consolidate to production slot or rearchitect to separate apps |\n| TLS/SSL certificates | ⚠️ Site-scoped certificates in preview | Re-add used certificates after migration, verify the per-app limits, and update code to use Linux certificate file paths |\n| Blob trigger (polling) | ❌ EventGrid source only | Convert `LogsAndContainerScan` → `EventGrid`; create event subscription |\n| Disable setting for function names containing `-` | ❌ Not supported on Linux | Isolate the target dependency, rename/repackage the function, use a source-first deployment cutover, or explicitly accept active-trigger risk |\n| Azure Government | ❌ Not available | Cannot migrate yet |\n| MSDeploy / FTP / Kudu git deploy | ❌ Not supported | Switch to `az functionapp deploy` or `func azure functionapp publish` |\n| PowerShell managed dependencies | ❌ Not supported | Package all required modules in the app-root `Modules` folder before deployment; verify Linux compatibility. `requirements.psd1` alone doesn't install modules on Flex Consumption. See [PowerShell dependency management](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-powershell#dependency-management). |\n\n#### Windows-to-Linux Specific Blockers\n\n| Issue | How to Detect | Action Required |\n|-------|---------------|-----------------|\n| .NET in-process model | `FUNCTIONS_WORKER_RUNTIME=dotnet` app setting | Migrate to isolated worker model — requires code changes (different NuGet packages, `Program.cs` startup) |\n| .NET Framework targeting (`net4x`) | `.csproj` target framework | Retarget to .NET 8+ — may require replacing Framework-only APIs and NuGet packages |\n| Windows-only NuGet packages (GDI+, COM, P/Invoke) | Assembly/package scan (heuristic) | Replace with cross-platform alternatives, or migrate to Elastic Premium on Windows |\n| Windows RID deployment package | `runtimes/win-x64/` present without `linux-x64` in package | Republish without a RID (framework-dependent) or with `-r linux-x64` |\n| Path separator / case sensitivity | Code review | Replace `\\` path construction with `Path.Combine()`; fix case-sensitive file references |\n| PowerShell Windows-only modules (WMI, registry, COM) | `requirements.psd1` module imports | Replace with cross-platform alternatives or remove |\n| Windows certificate store access | Code review | Migrate to file-based certificate loading |\n| Unsupported language runtime version | Site config | Upgrade to a [supported version](https://learn.microsoft.com/en-us/azure/azure-functions/supported-languages) |\n| App region not supported by Flex | Region vs. Flex availability list | Wait for regional availability, or relocate the app |\n\n> 💡 **Elastic Premium escape hatch**: Apps with hard Windows dependencies that cannot be removed can migrate to [Elastic Premium on Windows](https://learn.microsoft.com/en-us/azure/azure-functions/functions-premium-plan) as an alternative. This changes the hosting plan without requiring an OS migration.\n\n## New App Name\n\nThe new Flex Consumption app needs a globally unique name. The skill defaults to **`\u003csource>-flex`** — e.g. if your source app is `test-app`, the new app will be `test-app-flex`. This is short, self-documenting, and signals the SKU change.\n\nTwo modes are supported. State your preference in your initial migration request:\n\n| Mode | How to invoke | Resulting name |\n|------|---------------|----------------|\n| **Default suffix** *(default)* | Just say \"migrate my function app\" | `\u003csource>-flex` |\n| **Custom name** | \"migrate my function app **as `\u003cname>`**\" or \"… **named `\u003cname>`**\" | The name you provide |\n\n> ⚠️ **Skill instruction**: Before executing Step 4b in [automation.md](automation.md), **announce the proposed name to the user**, e.g. *\"I'll create the new Flex app as `test-app-flex` in resource group `test-app_group` (region `westus2`). Say so if you'd prefer a different name.\"* This gives the user a chance to course-correct without a blocking prompt.\n\n> 💡 Constraints (from the underlying [MS Learn create flow](https://learn.microsoft.com/en-us/azure/azure-functions/flex-consumption-how-to?tabs=azure-cli%2Cazure-cli-publish&pivots=programming-language-csharp#create-a-flex-consumption-app)): globally unique in Azure (becomes `\u003cAPP_NAME>.azurewebsites.net`), 2–60 characters, alphanumerics + hyphens, must start with a letter, no consecutive hyphens. If the default `\u003csource>-flex` would exceed 60 chars or collides with an existing app, fall back to a shortened suffix (e.g. `\u003csource>-fc`) and announce that to the user.\n\n## Storage Account Options\n\nThe new Flex Consumption app needs a storage account bound at creation time. The skill defaults to **reusing the source app's existing storage account** — the same default as `az functionapp flex-migration` on Linux. This is the lowest-friction option because there is no new storage resource to manage. Flex configures deployment storage on the target rather than reusing the source app's Windows content-share settings.\n\nThree modes are supported. State your preference in your initial migration request — the skill will detect it and set the binding accordingly. Think of these as CLI-style flags:\n\n| Mode | How to invoke | When to use |\n|------|---------------|-------------|\n| **Reuse source storage** *(default)* | Just say \"migrate my function app\" | Most migrations. No isolation needed between source and target. |\n| **Create new storage** | \"migrate my function app **with a new storage account**\" or \"… **and create a new storage account**\" | You want isolated storage for blast-radius, compliance, or test/prod separation. |\n| **Use a specific existing account** | \"migrate my function app **using storage account `\u003cname>`**\" | You already have a target account provisioned (e.g. via IaC or central platform team). |\n\n> ⚠️ **Skill instruction**: Before executing Step 4a/4b in [automation.md](automation.md), **announce the storage choice to the user**, e.g. *\"I'll reuse your existing storage account `foo` for the new Flex app. Say so if you'd prefer a new isolated account or a different existing one.\"* This gives the user a chance to course-correct without a blocking prompt.\n\n## Upgrade Phases\n\nInitialize and maintain `\u003cUPGRADE_DIR>/upgrade-status.md` using [Migration Progress](progress-tracking.md). Derive its workflow snapshot from the current scenario and automation headings, and show the current phase, substep, description, and state in chat at every transition; do not use a percentage.\n\n### Phase 1: Assessment\n\nRun all checks from [assessment.md](assessment.md). Since `az functionapp flex-migration` does not support Windows, eligibility is determined manually — use Step 1 and Step 2 in [automation.md](automation.md) to identify candidate apps and run compatibility checks.\n\n- **Source code dependency scan** ([Step 2g](automation/discovery-and-assessment.md#2g-source-code-windows-dependency-scan) / [dependency-scan.md](dependency-scan.md)) — recommended for every Windows → Flex migration. Prefer a local source directory or checked-out repository; use the deployed package only when source is unavailable. The scan checks for Win32/COM/WMI/registry/cert-store usage, Windows-only packages, Windows-RID targeting, and shell-outs to Windows tools. Skippable — when skipped, the user owns the risk. Findings populate §11 of the assessment report and advisorily affect §1 `Upgrade Readiness`.\n\n### Phase 2: Pre-migration (Collect Everything)\n\nCollect all settings and configurations from the existing app before creating the new one. See **Step-by-step scripts** in [automation.md](automation.md):\n\n1. Collect app settings\n2. Collect application configurations (CORS, custom domains, HTTP version, TLS, client certs, etc.)\n3. Inventory TLS/SSL certificates that must be re-added with the site-scoped certificate process\n4. Identify managed identities and RBAC role assignments\n5. Identify built-in authentication settings\n6. Review inbound access restrictions\n7. Get the code deployment package (if source code not in version control)\n\n### Phase 3: Create Flex Consumption App\n\nExecute Steps 4a–4l from [automation.md](automation.md). Each sub-step handles a discrete part of the migration:\n\n- **4a** — *(optional)* Create a new storage account — only run if the user explicitly asked for new or different storage; see [Storage Account Options](#storage-account-options)\n- **4b** — Run the storage authentication preflight; use connection-string creation only when Shared Key access is permitted. Otherwise block for user-provisioned, verified identity-first creation — [App Creation](automation/app-creation.md#4b-create-the-flex-consumption-app)\n- **4b.opt** — Convert a permitted connection-string target to identity-based storage if the source was identity-based or the user requested it; not a workaround for prohibited Shared Key access\n- **4c** — Review app-setting names, then ask whether to copy filtered source settings or defer them until target-specific dependencies are configured\n- **4d** — Apply site configurations (HTTP/2, TLS, HTTPS-only, client certs, SCM basic auth)\n- **4e** — Migrate system-assigned managed identity and role assignments\n- **4f** — Migrate user-assigned managed identities\n- **4f.auth** — If the source uses built-in authentication, configure and validate each provider before code deployment or defer the migration\n- **4g** — Migrate CORS settings\n- **4h** — Migrate custom domains\n- **4i** — Migrate access restrictions\n- **4j** — Skip disablement when settings and every trigger dependency are proven isolated from production and no autonomous function can affect production; otherwise separate hyphenated non-HTTP function names, which Linux cannot disable through app settings, and obtain the applicable safety decisions — [decision guidance](automation/trigger-safety-and-monitoring.md#4j-choose-the-pre-deployment-state-of-non-http-functions)\n- **4k** — Verify the Application Insights configuration created with the target app; preserve AAD ingestion only when the source used it\n- **4l** — Inventory access-key names and choose target-generated keys or opt in to preserving source host and HTTP-function key values\n\n> 💡 Use Microsoft Entra ID + managed identities instead of connection strings when creating the new app.\n\n### Identity-First Configuration (Functions)\n\nEnterprise subscriptions commonly enforce policies blocking local auth. Configure identity-based access:\n\n- **Storage accounts**: [Step 4b](automation/app-creation.md#4b-create-the-flex-consumption-app) checks Shared Key access and policy before creation. Where keys are prohibited, managed identity and effective roles are required for both runtime and deployment storage; block until identity-first provisioning is verified. Runtime identity settings alone don't configure deployment identity. [4b.opt](automation/app-creation.md#4bopt-identity-based-storage) is a post-create conversion only where connection-string creation was permitted. Step 4c preserves target storage settings rather than copying source `AzureWebJobsStorage*` settings.\n- **Application Insights**: Preserve `Authorization=AAD` when the source already uses it; otherwise treat conversion as optional post-migration hardening\n- When using User Assigned Managed Identity, pass `managedIdentityClientId` explicitly\n\n### Phase 4: Verify and Configure the New App\n\nSteps 4a–4i migrate application configuration; Step 4f.auth handles built-in authentication; Steps 4j–4k establish trigger safety and verify monitoring; Step 4l records the access-key strategy. Verify the results and manually configure anything not covered by those steps (see [automation.md](automation.md)):\n\n1. **Verify** the chosen app-setting mode, identities, and custom domains\n2. **Re-add** used TLS/SSL certificates with the site-scoped certificate process and update code that used the Windows certificate store\n3. **Configure** the source app's custom scale limit, if one was set\n4. **Verify** Application Insights monitoring\n\n### Phase 5: Deploy Code\n\n> ⚠️ **Code is NOT automatically migrated.** The new app is created with config only — you must deploy code separately.\n>\n> ⚠️ If Step 4b storage authentication preflight or identity-first provisioning remains blocked, do not deploy code. Required storage identities, role assignments, and access validation cannot be deferred.\n>\n> ⚠️ If source app settings were deferred in Step 4c, deployment is blocked until the user confirms all required application-specific target settings are configured. The skill may inspect names, but never setting values.\n>\n> ⚠️ If built-in authentication was deferred in Step 4f.auth, deployment is blocked. The source authentication boundary must be recreated and verified before application code is placed on the target.\n\n**Use `ask_user` to present these options:**\n\n> Your new Flex Consumption app `\u003cNEW_APP_NAME>` has been created and configured. Now we need to deploy your function code. How would you like to proceed?\n>\n> 1. **Update CI/CD pipeline** — I'll help you update your Azure Pipelines or GitHub Actions workflow to target the new app\n> 2. **Deploy from local project** — I'll run `func azure functionapp publish \u003cNEW_APP_NAME>` from your project directory\n> 3. **Deploy existing package** — I'll deploy the package we downloaded earlier from the original app\n\nAfter user selects an option, execute the corresponding deployment method from [automation.md](automation.md) — Step 5.\n\nAfter deployment synchronizes all functions, execute Step 5a. When preservation was selected, copy and verify source host and HTTP-function keys before any HTTP validation. System and master keys remain target-generated.\n\n> ✅ If Step 4j disablement was approved and no risky hyphenated non-HTTP function was approved for active deployment, only HTTP endpoints will be live after deployment and per-function cutover happens in Phase 6.\n>\n> ✅ If Step 4j was skipped because the target is fully isolated, deploy without per-function disable settings and validate only against those isolated dependencies.\n>\n> ⚠️ If the user declined disablement, warn again and obtain explicit approval immediately before deployment because non-HTTP functions may begin processing or running schedules as soon as deployment completes.\n\n**After successful deployment, inform the user:**\n\n> Code deployed! Next steps to consider:\n>\n> - The original app is still running — keep it as rollback for a few days\n> - If target-generated access keys were selected, update key-dependent clients and workflows before directing them to the new URL\n> - Enable HTTPS-only and managed identity on the new app for better security\n> - Source deletion is available only after all applicable production traffic and triggers are cut over and validated\n\n### Phase 6: Post-Upgrade Validation\n\n1. **Smoke test** — Get the app's default hostname via `az functionapp show --query defaultHostName -o tsv`, then hit that URL and confirm it returns a non-error response (HTTP 2xx/4xx, not connection refused or 503). If an intentional access restriction returns `403 Ip Forbidden`, verify deployment and function synchronization through ARM and record functional smoke testing as deferred until it can run from an already allowed client; do not relax access rules automatically.\n2. Verify the app is running on Flex Consumption (`az functionapp show --query sku`)\n3. Test HTTP trigger endpoints (e.g. `curl https://\u003cDEFAULT_HOST>/api/\u003cFUNCTION_NAME>`)\n4. **Per-function validation and cutover for event-driven triggers** — either validate the target against isolated test resources without changing the source, or use a production cutover transaction. For production, obtain function-specific approval first, disable and verify the source, then enable the target; the same approval must explicitly authorize rollback if target validation fails. Never enable a production-connected target while source-disable approval is pending. See [Per-Function Cutover](automation/validation-and-cutover.md#per-function-cutover-event-driven-triggers) for the full procedure.\n5. Capture and compare performance benchmarks\n6. Set up monitoring dashboards\n7. Refine scale/concurrency settings\n8. Update IaC (Bicep/Terraform) to reflect new plan\n\n### Phase 7: Cleanup (Optional)\n\n- Keep the original app for a few days/weeks as rollback\n- Consumption plan charges only for actual usage — low cost to keep idle\n- A validation-only success is not eligible for source deletion\n- The skill may offer deletion only when the recorded outcome is `production cutover complete`, no production-readiness work remains deferred, and the source no longer processes production workloads\n- Immediately before deletion, use `ask_user` as specified in [automation.md](automation.md) — Step 7\n\n## Trigger Migration Risks\n\n> ✅ **Recommended safety net**: When the user approves [Step 4j](automation/trigger-safety-and-monitoring.md#4j-choose-the-pre-deployment-state-of-non-http-functions), non-HTTP functions are disabled before deployment. Phase 6 then uses isolated target resources or a source-first, pre-approved production transaction so the target is never enabled while source-disable approval is pending. If the user declines Step 4j, record that dual processing or duplicate schedules may begin immediately after deployment. Apply the relevant mitigations below before enabling or deploying each function.\n\n| Trigger Type | Risk | Mitigation |\n|-------------|------|------------|\n| Azure Blob storage | High | Create separate container for event-based trigger in new app |\n| Azure Cosmos DB | High | Create dedicated lease container for new app; set `StartFromBeginning: false` |\n| Azure Event Grid | Medium | Recreate event subscriptions; ensure idempotent functions |\n| Azure Event Hubs | Medium | Create new consumer group for new app |\n| Azure Service Bus | High | Create new topic/queue; update senders; drain original before shutdown |\n| Azure Storage Queue | High | Create new queue; update senders; drain original before shutdown |\n| HTTP | Low | Update clients to target new app URL |\n| Timer | Low | Offset schedules during cutover to avoid simultaneous execution |\n\n## IaC Key Differences\n\n| Property | Consumption | Flex Consumption |\n|----------|-------------|------------------|\n| SKU | `Y1` (Dynamic) | `FC1` (FlexConsumption) |\n| Plan required | Optional (auto-created) | Required (must be explicit) |\n| OS | Windows | Linux |\n| Configuration | App settings | `functionAppConfig` section |\n| Storage | `WEBSITE_CONTENTSHARE` setting | `deployment.storage` in `functionAppConfig` |\n\nIf the source app is managed through Bicep, ARM, or Terraform:\n\n1. Define the Flex app and plan as new resources; a Consumption app cannot be converted to Flex Consumption in place.\n2. Update the deployment definitions to use the new resource names and the Flex configuration above.\n3. Reconcile resources created during migration instead of allowing IaC to recreate or overwrite them. For Terraform, import the new resources when appropriate.\n4. Review the proposed changes with `az deployment group what-if` or `terraform plan` before applying them.\n5. Update CI/CD pipelines to deploy to the new Flex app.\n\nDo not mix ongoing manual configuration with resource-based deployments. If the app is not managed through IaC, skip this section.\n\n## Deprecated Settings (Do NOT Migrate)\n\nThese app settings must be filtered out before applying to the new Flex app (Step 4c). The skill handles this automatically — Step 4c streams source settings through `jq`, deleting these keys in memory before PATCHing the new app's ARM endpoint.\n\n### Azure Files content settings (always present on Windows Consumption — never migrate)\n\nEvery Windows Consumption app has these because the platform requires them for the Azure Files SMB share. Flex uses blob-based deployment instead — these have no equivalent.\n\nThese platform content settings are distinct from explicit Azure Files mount metadata returned by `az webapp config storage-account list`. Windows Consumption doesn't support explicit storage mounts, so catalog any returned metadata but don't migrate it.\n\n- `WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`\n- `WEBSITE_CONTENTSHARE`\n- `WEBSITE_CONTENTOVERVNET`\n- `WEBSITE_SKIP_CONTENTSHARE_VALIDATION`\n\n### Deployment settings (Flex uses `deployment.storage` in `functionAppConfig`, not app settings)\n\nWindows Consumption has three historical aliases for run-from-package — all must be removed:\n\n- `WEBSITE_RUN_FROM_PACKAGE`\n- `WEBSITE_RUN_FROM_ZIP` (legacy alias — same semantics as `WEBSITE_RUN_FROM_PACKAGE`)\n- `WEBSITE_USE_ZIP` (original name — same semantics)\n\n### Runtime / scale settings (configured via `functionAppConfig` in Flex, not app settings)\n\n- `FUNCTIONS_EXTENSION_VERSION`\n- `FUNCTIONS_WORKER_RUNTIME`\n- `FUNCTIONS_WORKER_RUNTIME_VERSION`\n- `FUNCTIONS_MAX_HTTP_CONCURRENCY`\n- `FUNCTIONS_WORKER_PROCESS_COUNT`\n- `FUNCTIONS_WORKER_DYNAMIC_CONCURRENCY_ENABLED`\n- `WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT`\n\n### Other unsupported settings\n\n- `WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED`\n- `WEBSITE_LOAD_CERTIFICATES` (unused in Flex; use the site-scoped certificate process and make certificates accessible to app code)\n- `AzureWebJobsDashboard` (legacy v1 setting — not used by the v4 runtime)\n- `WEBSITE_MOUNT_ENABLED`\n- `ENABLE_ORYX_BUILD`\n- `SCM_DO_BUILD_DURING_DEPLOYMENT`\n- `WEBSITE_DNS_SERVER`\n- `WEBSITE_NODE_DEFAULT_VERSION`\n- `WEBSITE_VNET_ROUTE_ALL`\n\n### Application Insights (preserved from Step 4b and verified by Step 4k)\n\n- `APPLICATIONINSIGHTS_CONNECTION_STRING` — Step 4c preserves the target-specific value normally created by `az functionapp create`; Step 4k verifies it without displaying the value. `APPLICATIONINSIGHTS_AUTHENTICATION_STRING=Authorization=AAD` is preserved only when the source already used AAD ingestion.\n\n### Storage (replaced by Step 4b / 4b.opt)\n\nEvery setting whose name starts with `AzureWebJobsStorage` is dropped by the 4c filter. Preserve the target binding verified by Step 4b or configured by [Step 4b.opt](automation/app-creation.md#4bopt-identity-based-storage):\n\n- `AzureWebJobsStorage` — discard the source connection string. Step 4b creates a fresh target connection string only when Shared Key authentication is permitted; identity-first targets must not receive one.\n- All `AzureWebJobsStorage__*` variants — discard source settings so they can't silently point the target runtime at the wrong account. Preserve verified target identity settings or re-derive them through 4b.opt where conversion is permitted.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":28555,"content_sha256":"fbeacdddf4c44cef33f3dc18679eec48a355c80a72622d729dee2ebe1ea669d5"},{"filename":"references/services/redis/redis-to-amr.md","content":"# Azure Cache for Redis → Azure Managed Redis (AMR) Migration\n\n> **Target for both paths**: Azure Managed Redis (AMR) — M, B, X (Flash), A series\n> **Source determines which dedicated skill to install** — see decision table below.\n\nThere are **two distinct migration paths** to AMR, depending on the source SKU. Each path is owned by a dedicated, versioned skill maintained by the Azure Managed Redis team. The `azure-upgrade` skill does **not** ship the SKU specs, pricing scripts, ARM automation, or template-transformation logic needed for either migration — it routes the user to the correct dedicated skill.\n\n## Decision Table — Which Skill?\n\n| Source SKU | ARM Resource Type | CLI / PowerShell | Dedicated Skill | Repo |\n|---|---|---|---|---|\n| **ACR / OSS Redis** — Basic, Standard, Premium (C0–C6, P1–P5) | `Microsoft.Cache/redis` | `az redis`, `*-AzRedisCache` | `amr-migration-skill` | https://github.com/AzureManagedRedis/amr-migration-skill |\n| **ACRE** — Enterprise (`Enterprise_E*`), Enterprise Flash (`EnterpriseFlash_F*`) | `Microsoft.Cache/redisEnterprise` | `az redisenterprise`, `*-AzRedisEnterprise*` | `acre-to-amr-migration-skill` | https://github.com/AzureManagedRedis/acre-to-amr-migration-skill |\n\n> ACR and ACRE are **fundamentally different products** with different ARM resource types, different APIs, and different migration mechanics. Picking the wrong skill will give the user wrong guidance. Always disambiguate before pointing.\n\n## Disambiguation — How to Tell ACR from ACRE\n\nAsk the user, or inspect the resource. Any **one** of these signals identifies the source:\n\n**ACR (OSS) indicators** → use `amr-migration-skill`:\n- Resource type `Microsoft.Cache/redis` (no \"Enterprise\" suffix)\n- SKU names `Basic`, `Standard`, `Premium`, or sizes `C0`–`C6`, `P1`–`P5`\n- CLI: `az redis ...` commands\n- PowerShell: `New-AzRedisCache`, `Get-AzRedisCache`, etc.\n- DNS suffix `.redis.cache.windows.net`\n- Default TLS port `6380`\n\n**ACRE indicators** → use `acre-to-amr-migration-skill`:\n- Resource type `Microsoft.Cache/redisEnterprise`\n- SKU names starting with `Enterprise_` (e.g. `Enterprise_E10`, `Enterprise_E20`) or `EnterpriseFlash_` (e.g. `EnterpriseFlash_F300`)\n- CLI: `az redisenterprise ...` commands\n- PowerShell: `New-AzRedisEnterpriseCache`, `Get-AzRedisEnterpriseCache`, etc.\n- Default TLS port `10000`\n- May reference geo-replication groups (`databases create-replica-link`), Private Endpoints, or Private Link DNS zones\n\nIf the user has a **mix of ACR and ACRE** resources, both skills should be installed and run separately on the relevant resources. Most users (~97% of the Azure Cache for Redis fleet) are on ACR; ACRE is the smaller (~3%) but functionally distinct case.\n\n## What Each Skill Provides\n\n### `amr-migration-skill` (ACR/OSS → AMR)\n\n- SKU mapping ACR Basic/Standard/Premium → AMR M/B/X/A with validated SKU specs\n- Real-time pricing scripts (PowerShell + bash) with HA, clustering, and MRPP logic\n- Cache metrics assessment (default 7-day window) for sizing\n- Automated migration via ARM REST APIs with **DNS switching** (old hostname keeps working; port still changes)\n- Validate-before-migrate workflow with explicit confirmation on destructive actions\n- IaC template migration for ARM, Bicep, and Terraform with worked before/after examples\n- Feature comparison and retirement FAQ\n- **Retirement deadlines this skill addresses**: ACR Basic/Standard/Premium tiers are being retired — for the current retirement and creation-block dates, see the [official ACR retirement announcement](https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-retired-tiers).\n\n### `acre-to-amr-migration-skill` (ACRE → AMR)\n\n- Three modes: automation-script update (ARM/Bicep/CLI/PowerShell/Terraform checklist), interactive cache migration with confirmation gates, generic step-by-step guide\n- ACRE → AMR SKU resolution via `listSkusForScaling` with fallback mapping table\n- In-place migration for standalone caches; create-new-and-swap for geo-replicated caches\n- Geo-replication database config parity (eviction policy, modules, etc.)\n- Private Endpoint / Private Link migration and DNS zone updates\n- Breaking-changes reference (property changes, DNS, API versions)\n- Reusable polling scripts (`Poll-MigrationStatus.ps1`, `poll-migration-status.sh`)\n- Post-migration ACRE resource cleanup\n- **Retirement deadline this skill addresses**: ACRE / Enterprise Flash are being retired — for the current retirement date, see the [official ACR retirement announcement](https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-retired-tiers).\n\n## Agent Behavior\n\nWhen a user asks about migrating any flavor of Azure Cache for Redis to Azure Managed Redis:\n\n1. **Do not attempt the migration from this skill.** Neither SKU specs nor migration automation are inlined here.\n2. **Determine the source** using the disambiguation signals above. If unclear, ask the user (or inspect the script/resource).\n3. **Point the user to the correct dedicated skill** with its repo URL. The repo READMEs include install instructions for GitHub Copilot, Claude Code, and other compatible hosts.\n4. After installation, the user's agent will match the dedicated skill on its trigger phrases (e.g. *\"migrate my P2 cache to AMR\"*, *\"convert my Bicep Redis template\"*, *\"migrate my Enterprise_E10 cache\"*, *\"update my ACRE ARM template for AMR\"*).\n5. If the user has **both** ACR and ACRE resources, recommend installing **both** skills and running them on the relevant resources separately.\n\n## Key Migration Facts (so the agent can set expectations)\n\nThese are summarized for awareness. For anything operational, defer to the dedicated skills.\n\n### ACR → AMR\n- **Port**: 6380 → **10000**. Non-TLS 6379 not supported on AMR.\n- **DNS suffix**: `.redis.cache.windows.net` → `\u003cregion>.redis.azure.net`\n- **Redis version**: 6 → **7.4**\n- **No \"shards\"** in AMR-facing terminology — sharding is internal. Use performance tier (Balanced, Memory Optimized) and size (e.g. B10, M20).\n- **Auth**: Recommend adopting **Microsoft Entra ID** post-migration. Entra config is **not** auto-migrated.\n- **DNS-switch automated migration** keeps old hostname working, but the port change still applies — apps must be updated.\n\n### ACRE → AMR\n- **ARM resource type is unchanged** between the ACRE source and AMR target — both use `Microsoft.Cache/redisEnterprise`. Property values do change (API version, SKU naming, etc.); see the breaking-changes reference in the dedicated skill.\n- **Geo-replicated caches** require create-new-and-swap, not in-place migration.\n- **Private Endpoints / Private Link** DNS zones must be updated.\n- **Database config parity** (eviction policy, modules) must match across replicas before migration.\n\n## Why this is not implemented inline\n\nBoth migrations require maintained SKU tables, live pricing or capability lookups, and ARM-level orchestration that is updated independently of the `azure-skills` release cycle. Keeping that logic in two places would drift. The dedicated skill repos are the single source of truth and are versioned independently.\n\n## References\n\n- AMR Migration Skill (ACR → AMR): https://github.com/AzureManagedRedis/amr-migration-skill\n- ACRE → AMR Migration Skill: https://github.com/AzureManagedRedis/acre-to-amr-migration-skill\n- Azure Managed Redis docs: https://learn.microsoft.com/en-us/azure/redis/managed-redis/\n- ACR retirement announcement: https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-retired-tiers\n- Entra ID auth for AMR: https://learn.microsoft.com/en-us/azure/redis/managed-redis/managed-redis-entra-for-access-control-configuration\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7700,"content_sha256":"9698e152e2d97067013b1ad6600d2a429505f5b15b24a7255f075cc741f9e136"},{"filename":"references/workflow-details.md","content":"# Workflow Details\n\n## Upgrade Workflow Phases\n\nThe azure-upgrade skill follows a structured workflow to ensure safe, repeatable upgrades.\n\n## Phase Overview\n\n```\n┌──────────┐ ┌──────────┐ ┌─────────────┐ ┌─────────┐ ┌──────────┐\n│ Identify │───▶│ Assess │───▶│ Pre-migrate │───▶│ Upgrade │───▶│ Validate │\n└──────────┘ └──────────┘ └─────────────┘ └─────────┘ └──────────┘\n```\n\n## Progress Tracking\n\nCreate and maintain `\u003cUPGRADE_DIR>/upgrade-status.md` (see [Artifact Output Policy](global-rules.md#artifact-output-policy) for path resolution):\n\n```markdown\n# Upgrade Status\n\n## Upgrade Details\n\n| Property | Value |\n|----------|-------|\n| **Source App** | \u003capp-name> |\n| **Source Plan** | \u003ccurrent-plan> |\n| **Target Plan** | \u003ctarget-plan> |\n| **Resource Group** | \u003cresource-group> |\n| **Region** | \u003cregion> |\n| **Started** | \u003cdate> |\n\n## Phase Status\n\n- [ ] Phase 1: Identify — Determine source/target plans\n- [ ] Phase 2: Assess — Check readiness and compatibility\n- [ ] Phase 3: Pre-migrate — Collect settings and configurations\n- [ ] Phase 4: Upgrade — Execute upgrade automation\n- [ ] Phase 5: Validate — Verify new app functionality\n\n## Notes\n\n\u003cany issues, decisions, or observations during upgrade>\n```\n\n## Error Handling\n\nIf any phase fails:\n1. Log the error in `\u003cUPGRADE_DIR>/upgrade-status.md`\n2. Do NOT proceed to the next phase\n3. Inform the user of the failure and suggest remediation\n4. Offer to retry the failed phase or rollback\n\n## Hand-off\n\nAfter successful validation:\n- Offer to hand off to `azure-validate` for deeper testing\n- Offer to hand off to `azure-deploy` for CI/CD pipeline setup\n- Ask about source cleanup only when the scenario confirms production cutover and all cleanup prerequisites are complete. Otherwise state that the source is being retained for rollback.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2135,"content_sha256":"529090e219af1bc54cdca33abade7850fc18b543d765d698631933025f70a971"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Azure Upgrade","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"This skill handles ","type":"text"},{"text":"assessment and automated upgrades","type":"text","marks":[{"type":"strong"}]},{"text":" of existing Azure workloads from one Azure service, hosting plan, or SKU to another — all within Azure. This includes plan/tier upgrades (e.g. Consumption → Flex Consumption), cross-service migrations (e.g. App Service → Container Apps), and SKU changes. It also covers ","type":"text"},{"text":"Azure SDK for Java source-code modernization","type":"text","marks":[{"type":"strong"}]},{"text":" (e.g. legacy Java ","type":"text"},{"text":"com.microsoft.azure.*","type":"text","marks":[{"type":"code_inline"}]},{"text":" → modern ","type":"text"},{"text":"com.azure.*","type":"text","marks":[{"type":"code_inline"}]},{"text":"). This is NOT for cross-cloud migration — use ","type":"text"},{"text":"azure-cloud-migrate","type":"text","marks":[{"type":"code_inline"}]},{"text":" for that.","type":"text"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Triggers","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"User Intent","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Example Prompts","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Upgrade Azure Functions plan","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Upgrade my function app from Consumption to Flex Consumption\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Discover Functions upgrade candidates","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"What Consumption Function Apps do I have that can be upgraded to Flex Consumption?\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Change hosting tier","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Move my function app to a better plan\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Assess upgrade readiness","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Is my function app ready for Flex Consumption?\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Automate plan migration","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Automate the steps to upgrade my Functions plan\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Modernize legacy Azure Java SDK","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Migrate legacy Azure SDKs for Java\", \"Upgrade legacy Azure Java SDK\", \"Migrate my Java project from com.microsoft.azure to com.azure\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Migrate Azure Cache for Redis (ACR/OSS) to Azure Managed Redis (AMR)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Migrate my Redis cache to AMR\", \"ACR to AMR\", \"OSS to AMR\", \"Upgrade my Premium P2 cache to Managed Redis\", \"Pick an AMR SKU\", \"Convert my Redis IaC template to AMR\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Migrate Azure Cache for Redis Enterprise (ACRE) to Azure Managed Redis (AMR)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Migrate my Enterprise_E10 cache to AMR\", \"ACRE to AMR\", \"Update my ACRE IaC template for AMR\", \"Migrate EnterpriseFlash to AMR\", \"Migrate my geo-replicated Enterprise Redis\"","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Rules","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Follow phases in order. Skip or defer work only when the selected scenario explicitly permits it, and record the reason in the migration status.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generate an assessment before any upgrade operations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Load the scenario reference and follow its rules","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"mcp_azure_mcp_get_azure_bestpractices","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"mcp_azure_mcp_documentation","type":"text","marks":[{"type":"code_inline"}]},{"text":" MCP tools","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Destructive actions require ","type":"text"},{"text":"ask_user","type":"text","marks":[{"type":"code_inline"}]},{"text":" — ","type":"text"},{"text":"global-rules","type":"text","marks":[{"type":"link","attrs":{"href":"references/global-rules.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Always confirm the target plan/SKU with the user before proceeding","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Propose a name for any new resource","type":"text","marks":[{"type":"strong"}]},{"text":" (default: ","type":"text"},{"text":"\u003csource>-\u003ctarget-suffix>","type":"text","marks":[{"type":"code_inline"}]},{"text":", e.g. ","type":"text"},{"text":"\u003csource>-flex","type":"text","marks":[{"type":"code_inline"}]},{"text":" for Flex Consumption migrations) and ","type":"text"},{"text":"announce the proposed name to the user before creating it","type":"text","marks":[{"type":"strong"}]},{"text":" so they can override without a blocking prompt. Same pattern applies to other newly-created resources (storage accounts, App Insights, etc.) — see the scenario reference for service-specific defaults.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Windows Consumption → Flex source-change gate","type":"text","marks":[{"type":"strong"}]},{"text":": treat the source app as read-only by default. Immediately before every command that would change its settings, triggers, state, deployment, bindings, or existence, use ","type":"text"},{"text":"ask_user","type":"text","marks":[{"type":"code_inline"}]},{"text":" to describe the exact change and obtain explicit approval. Approval is action-specific and cannot be reused for later source changes.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never delete or stop the original app without explicit user confirmation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Keep approval-gated workflows moving","type":"text","marks":[{"type":"strong"}]},{"text":": after each completed step, immediately perform the next read-only preflight. If the next action requires approval, invoke ","type":"text"},{"text":"ask_user","type":"text","marks":[{"type":"code_inline"}]},{"text":" in the same turn — never stop after merely announcing the next step and wait for the user to re-engage.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"All automation scripts must be idempotent and resumable","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Upgrade Scenarios","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Source","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Target","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reference","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Azure Functions Consumption Plan (Linux)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Azure Functions Flex Consumption Plan","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"workflow.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/functions/consumption-to-flex/linux/workflow.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Azure Functions Consumption Plan (Windows)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Azure Functions Flex Consumption Plan","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"workflow.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/functions/consumption-to-flex/windows/workflow.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Legacy Azure Java SDK (","type":"text"},{"text":"com.microsoft.azure.*","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Modern Azure Java SDK (","type":"text"},{"text":"com.azure.*","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"languages/java/README.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/languages/java/README.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Azure Cache for Redis (ACR/OSS) Basic/Standard/Premium","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Azure Managed Redis (AMR)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"services/redis/redis-to-amr.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/redis/redis-to-amr.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Azure Cache for Redis Enterprise (ACRE) / Enterprise Flash","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Azure Managed Redis (AMR)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"services/redis/redis-to-amr.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/redis/redis-to-amr.md","title":null}}]}]}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Functions Consumption-to-Flex routing:","type":"text","marks":[{"type":"strong"}]},{"text":" For a named app, inspect its Azure platform and load only the matching Linux or Windows workflow. For subscription-wide discovery, evaluate both platforms: use ","type":"text"},{"text":"az functionapp flex-migration list","type":"text","marks":[{"type":"code_inline"}]},{"text":" for Linux and the Windows workflow's manual discovery and compatibility checks for Windows. Label Windows results as candidates until per-app code compatibility is assessed.","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"SDK upgrade scenarios (e.g. Java legacy → modern) run a ","type":"text"},{"text":"source-code modernization flow","type":"text","marks":[{"type":"strong"}]},{"text":" that is distinct from Azure service/plan/SKU upgrades: follow the scenario reference, ","type":"text"},{"text":"not","type":"text","marks":[{"type":"strong"}]},{"text":" the Steps below.","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"No matching scenario? Use ","type":"text"},{"text":"mcp_azure_mcp_documentation","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"mcp_azure_mcp_get_azure_bestpractices","type":"text","marks":[{"type":"code_inline"}]},{"text":" tools to research the upgrade path.","type":"text"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"MCP Tools","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tool","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Purpose","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"mcp_azure_mcp_get_azure_bestpractices","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Get Azure best practices for the target service","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"mcp_azure_mcp_documentation","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Look up Azure documentation for upgrade scenarios","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"mcp_azure_mcp_appservice","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Query App Service and Functions plan details","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"mcp_azure_mcp_applicationinsights","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Verify monitoring configuration","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Steps","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Identify","type":"text","marks":[{"type":"strong"}]},{"text":" — Determine the source and target Azure plans/SKUs. Ask user to confirm.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Assess","type":"text","marks":[{"type":"strong"}]},{"text":" — Analyze existing app for upgrade readiness → load scenario reference (e.g., ","type":"text"},{"text":"workflow.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/functions/consumption-to-flex/linux/workflow.md","title":null}}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Pre-migrate","type":"text","marks":[{"type":"strong"}]},{"text":" — Collect settings, identities, configs from the existing app","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Upgrade","type":"text","marks":[{"type":"strong"}]},{"text":" — Execute the automated upgrade steps (create new resources, migrate settings, deploy code)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validate","type":"text","marks":[{"type":"strong"}]},{"text":" — Use the checks defined by the selected scenario: verify target resource state, applicable HTTP endpoints and non-HTTP triggers, and monitoring. If access restrictions or unavailable test resources prevent execution, record validation as deferred — never relax security automatically or report functional success.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Ask User","type":"text","marks":[{"type":"strong"}]},{"text":" — Offer performance validation and IaC updates. Offer source cleanup only when the selected scenario confirms production cutover and all cleanup prerequisites are complete.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Hand off","type":"text","marks":[{"type":"strong"}]},{"text":" to ","type":"text"},{"text":"azure-validate","type":"text","marks":[{"type":"code_inline"}]},{"text":" for deep validation or ","type":"text"},{"text":"azure-deploy","type":"text","marks":[{"type":"code_inline"}]},{"text":" for CI/CD setup","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Track progress in ","type":"text"},{"text":"\u003cUPGRADE_DIR>/upgrade-status.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — see ","type":"text"},{"text":"Artifact Output Policy","type":"text","marks":[{"type":"link","attrs":{"href":"references/global-rules.md#artifact-output-policy","title":null}}]},{"text":" for path resolution.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Global Rules","type":"text","marks":[{"type":"link","attrs":{"href":"references/global-rules.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Workflow Details","type":"text","marks":[{"type":"link","attrs":{"href":"references/workflow-details.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Functions","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Linux","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Consumption to Flex Consumption","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/functions/consumption-to-flex/linux/workflow.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Assessment","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/functions/consumption-to-flex/linux/assessment.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Automation Scripts","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/functions/consumption-to-flex/linux/automation.md","title":null}}]}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Windows","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Consumption to Flex Consumption","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/functions/consumption-to-flex/windows/workflow.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Assessment","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/functions/consumption-to-flex/windows/assessment.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Automation Scripts","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/functions/consumption-to-flex/windows/automation.md","title":null}}]}]}]}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Redis","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Redis (ACR or ACRE) to AMR Migration","type":"text","marks":[{"type":"link","attrs":{"href":"references/services/redis/redis-to-amr.md","title":null}}]},{"text":" — routes to dedicated ","type":"text"},{"text":"amr-migration-skill","type":"text","marks":[{"type":"link","attrs":{"href":"https://github.com/AzureManagedRedis/amr-migration-skill","title":null}}]},{"text":" (ACR/OSS) or ","type":"text"},{"text":"acre-to-amr-migration-skill","type":"text","marks":[{"type":"link","attrs":{"href":"https://github.com/AzureManagedRedis/acre-to-amr-migration-skill","title":null}}]},{"text":" (Enterprise)","type":"text"}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Java SDK Migration Templates","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Plan Template","type":"text","marks":[{"type":"link","attrs":{"href":"references/languages/java/templates/PLAN_TEMPLATE.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Progress Template","type":"text","marks":[{"type":"link","attrs":{"href":"references/languages/java/templates/PROGRESS_TEMPLATE.md","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Summary Template","type":"text","marks":[{"type":"link","attrs":{"href":"references/languages/java/templates/SUMMARY_TEMPLATE.md","title":null}}]}]}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Next","type":"text"}]},{"type":"paragraph","content":[{"text":"After upgrade is validated, hand off to:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"azure-validate","type":"text","marks":[{"type":"code_inline"}]},{"text":" — for thorough post-upgrade validation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"azure-deploy","type":"text","marks":[{"type":"code_inline"}]},{"text":" — if the user wants to set up CI/CD for the new app","type":"text"}]}]}]}]},"metadata":{"date":"2026-11-02","name":"azure-upgrade","author":"@skillopedia","source":{"stars":1612,"repo_name":"azure-skills","origin_url":"https://github.com/microsoft/azure-skills/blob/HEAD/skills/azure-upgrade/SKILL.md","repo_owner":"microsoft","body_sha256":"58ed42a87e5b5aee1cc07f970f05da8fd860037f8a0201ce7e68a88fbee79063","cluster_key":"d667526836f9ef69c99db7fe1bfdfe85383ed38ec34fce005573fa2940b2c57d","clean_bundle":{"format":"clean-skill-bundle-v1","source":"microsoft/azure-skills/skills/azure-upgrade/SKILL.md","text_bytes":329832,"source_commit":"bd001a39dc9d4fea4f4e488284a9cfbb05d4bf78","skills_sh_rank":149,"attachment_count":49,"text_attachments":49,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/azure-upgrade/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"devops-infrastructure","category_label":"DevOps"},"exact_dupes_collapsed_into_this":0},"license":"MIT","version":"v1","category":"devops-infrastructure","metadata":{"author":"Microsoft","version":"1.2.3"},"import_tag":"skills-sh-top20k-2026-11","description":"Assess and upgrade Azure workloads between plans, tiers, or SKUs, or modernize Azure SDK dependencies in source code. WHEN: upgrade Consumption to Flex Consumption, upgrade Azure Functions plan, change hosting plan, function app SKU, migrate App Service to Container Apps, modernize legacy Azure Java SDKs (com.microsoft.azure to com.azure), migrate Azure Cache for Redis (ACR/ACRE) to Azure Managed Redis (AMR).","compatibility":"python3.10+"}},"renderedAt":1793666293785}

Azure Upgrade This skill handles assessment and automated upgrades of existing Azure workloads from one Azure service, hosting plan, or SKU to another — all within Azure. This includes plan/tier upgrades (e.g. Consumption → Flex Consumption), cross-service migrations (e.g. App Service → Container Apps), and SKU changes. It also covers Azure SDK for Java source-code modernization (e.g. legacy Java → modern ). This is NOT for cross-cloud migration — use for that. Triggers | User Intent | Example Prompts | |-------------|-----------------| | Upgrade Azure Functions plan | "Upgrade my function ap…