The emulator family

repositories, one registry →

Your agent can write Azure-shaped code. Without a tenant it cannot prove it.

Clean-room emulators of the control planes nobody else emulates (Entra ID, ARM with real RBAC, Key Vault, API Management), and of the analytics engines behind a data product: Fabric, Databricks and Snowflake. Local, deterministic, free, and resettable in seconds.

So the agent builds, runs, reads the actual response and corrects itself hundreds of times before a person looks. Then the same code points at the real service by changing environment variables.

Every capability carries the test that proves it, and this page says which claims are proved by something that is not us, and which are not proved at all.

services emulated
control planes nobody else emulates
parity claims, each naming its witness
%of them proved by something that is not us
cells: one product, engines
orchestration idioms, same numbers

The problem this solves

It was never that an agent cannot write the code. It is that it cannot prove it, and proving an Azure-shaped system means a tenant.

The loop runs through a subscription

Minutes per round trip, state that does not reset, and a blast radius that makes an agent's normal behaviour, try it and look and try again, expensive and frightening. So the agent writes plausible code and a person spends weeks finding out where it was wrong.

docker compose down -v · a clean tenant in seconds, for free

The four parts you cannot stub honestly

Identity, authorization, secrets and a gateway come before anything interesting. A fake token issuer teaches an agent nothing about audience mismatches, and a permissive secret store teaches it nothing about RBAC. A permissive mock actively teaches the wrong thing.

separate processes, separate ports, real tokens validated over HTTP

Speed without fidelity is worse than slowness

An agent that iterates fast against a bad emulator converges fast on the wrong answer, and produces confident code that fails on first contact with Azure. Fidelity is not a nice-to-have here; it is the entire premise.

clean-room from published specification, never decompiled product code

How it fits together

Four cross-cutting planes in every stack, three analytics engines beside them, and one data product definition that every cell installs by tag rather than copying.

How the family fits together An agent or application talks to four cross-cutting emulators (Entra, ARM, Key Vault, APIM) and to one of three engine emulators (Fabric, Databricks, Snowflake). One core data product definition and one set of vendor systems feed seven cells, each a leaf product paired with a platform, which run against an engine emulator locally or against the real service unchanged. Your agent or your app Cross-cutting planes entra-emulator · the STS arm-emulator · RBAC azure-keyvault-emulator azure-apim-emulator Analytics engines fabric-emulator + OneLake databricks-emulator snowflake-emulator real Spark, real SQL behind them Seven cells leaf + platform, paired 3 engines · 5 idioms one product definition, one set of vendors, installed by tag The real service same code, different environment variables
The full inventory, generated from the registry, is in the map.

The family

Each emulator grades itself in a parity ledger, and every green row names the test that proves it. The figure on each card is the share of that emulator's claims proved by something that is not our own client: Microsoft's own SDK linked in process, or a packaged third-party client running in CI.

entra-emulator BOM

Entra ID, the STS. MSAL-compatible OIDC and OAuth2, issuing every token the others validate. The single highest-value one to adopt alone, because identity is the first thing that blocks local development.

arm-emulator BOM

The ARM control plane with Microsoft.Authorization role assignments, so “no assignment means no access” is something an agent discovers rather than something it is told. Scoped deliberately to the authorization slice, not all of ARM.

azure-keyvault-emulator BOM

The Key Vault data plane: secrets, real RSA and EC cryptography, X.509 certificates, with tokens validated against ARM's RBAC rather than accepted.

azure-apim-emulator BOM

Management plane, gateway and policy engine. The loop against a real APIM instance is minutes per policy edit, which is exactly the cost structure that makes agent-driven policy work impractical.

fabric-emulator BOM

Microsoft Fabric's control plane and OneLake, with a real Spark engine behind it: notebooks, Data Pipelines, a Warehouse over TDS, semantic models and Power BI over XMLA.

databricks-emulator BOM

The Azure Databricks workspace REST surface: Jobs, the Statement Execution API, Unity Catalog, PAT and OIDC identity with entra as an optional federated issuer.

snowflake-emulator adjacent

A Snowflake account on DuckDB, with the same discipline: a graded ledger, a witness manifest, and a checker enforcing both. Deliberately outside the certified compose and the chain test, so the family subtotal does not quietly include it.

graded ledger · not in the BOM · not in the chain test
The combination is certified, not just the parts.

azure-emulators holds the bill of materials, the pinned docker compose, and a chain test that runs the whole set together: of the emulators above. A family of parts that each pass alone is not the same claim.

One product, three engines

The concrete result, and the reason any of this is worth building.

The same Contoso data product runs on Fabric, on Databricks and on Snowflake, through orchestration idioms, from four real source systems through a medallion lakehouse to a semantic model. Every cell reproduces of revenue across sale lines.

Porting a data product across analytics engines is normally a project with a business case. It happened here because each attempt cost seconds instead of a tenant round trip, and because the comparison could tell an agent it was wrong without a human reading dataframes.

And every cell now asserts those figures on a nightly of its own.

Until recently the nightlies proved a pipeline had run and nothing about the answer: a cell whose gold silently returned different money would have stayed green indefinitely. All now hold their own published snapshot to figures the core repository states as data. Two of them turned out not to be writing a snapshot at all.

Honest status

The discipline here is that a claim is worth what checks it. The same rule applies to this page, so the rows that are not green are on it.

ClaimStatusWhat backs it, or what does not
Parity ledgers with enforced witnessesshipped green claims across the BOM, each bound to a named test in a witness manifest; CI fails on a dangling reference
Proved by something that is not usmeasured% per emulator, by Microsoft's own SDKs or packaged third-party clients in CI. Run family_parity.py --evidence yourself rather than trusting the snapshot
A pinned, chain-tested familyshippedA BOM, a certified compose and a chain test in azure-emulators
One product on three engineswitnessed cells, same three figures to the last digit, each asserted by its own unattended nightly
Diffed against real Azurenot runNo emulator here has Azure differential evidence. apim is the only ledger that defines the grade and it awards it zero times. Green means witnessed locally against real clients, which is a strong claim and a different one
The data product against a real tenantnot runfabric-emulator's real-Fabric conformance job exists and skips: the credentials are incomplete, so the gate reports it and the job never runs. The workflow is green with that leg untested, which is why it says so out loud
snowflake-emulator in the BOMdeliberately notSame discipline and a graded ledger, but outside the certified compose and the chain test. Joining would change what the family subtotal means, which is a release-coordination decision rather than a naming one
Breadth of Azure servicesnarrow on purposeSeven services deep, not eighteen shallow. If you want breadth-first coverage, the comparison says where the alternatives are better
arm-emulator's scopescopedIt reads in the nineties on both metrics, on a ledger its own boundary scopes to the authorization slice rather than all of ARM. A near-perfect score on a deliberately narrow slice is the row most likely to be misread
Clean-room constructionenforcedFrom published specification and observed protocol behaviour. Nothing decompiled is ever committed, only protocol facts

Built on it

Not part of the family. Things built with it, each running locally against these emulators and unchanged against real Azure.

data-agent-service shipped

Natural-language questions over the warehouses, databases and APIs you already have, grounded in the glossary and metrics held in OpenMetadata and fronted by API Management. Each query is authorized twice: role rules in the service, then the engine under the caller's own identity.

two executor images · every configured source · MCP, client-agnostic

data-agent-voice plan and scaffolding

The Analyst Line: ask aloud, and hear the answer with the definition it applied. Built around a measured gap. A question upstream takes twenty-six seconds at the median and a conversation reads as broken after about one, so the conversation stops waiting for the agent.

no audio has ever been through it; its ledger says so

sqlglot-go shipped

A Go port of sqlglot, verified statement by statement against the Python reference. Scoped to what a read-only SQL guard needs and built outward, which is what lets the Go executor above be a static binary on distroless.

verified against the reference implementation, statement by statement

The whole ecosystem

Generated from members.json, and CI fails when the picture and the registry disagree. The shapes are the ontology, not decoration: colour is the tier, a row is a cell, and a cell is always a leaf plus a platform.

One data product definition and one set of vendor systems feed seven cells. Each cell is a leaf paired with a platform, grouped under the engine emulator it targets, with four cross-cutting emulators in every stack.

Start

Three doors in, depending on whether you want the emulators, a whole data product, or one piece of either.

The emulators, on their own. The certified set, pinned together.

git clone https://github.com/calvinchengx/azure-emulators
cd azure-emulators
docker compose up                        # entra + keyvault + arm
docker compose --profile fabric up       # ...and fabric
docker compose --profile databricks up   # ...or the Databricks workspace

A whole data product, end to end. One launcher over every cell, reading the pair, the verbs and the ports from the registry.

git clone https://github.com/calvinchengx/emulators
cd emulators
./family ls                          # every cell, its two repos, its ports
./family up fabric-airflow3          # tells you which siblings to clone, if any
./family witness fabric-airflow3     # exit 0 only if the numbers hold
./family down fabric-airflow3

One piece. Plenty of agent work needs only identity, or only identity plus RBAC. Working à la carte says which combination answers which question, and getting started has the rest of the commands.

Give the agent the reset, and the ledger.

docker compose down -v between attempts is what stops a corrupted run from poisoning the next twenty. And when an agent hits a wall, the first question is whether the emulator claims that capability at all. The parity ledger answers it in one grep, which is cheaper than the agent inventing a workaround for something deliberately absent.