Notes / · 8 min
More than one Power BI supplier? The repo belongs in the client's tenant
When internal analysts and external suppliers build reports together, versions live on laptops and knowledge leaves with whoever leaves. Four rules for putting Power BI and Fabric under version control that the company - not the supplier - owns.
A common picture in mid-sized and large companies: Power BI reports are built by a small internal team plus one or two external suppliers. Each works in their own files. Which version is in production is known by whoever published last. When a supplier’s contract ends, the history of why a measure looks the way it does ends with it.
Power BI and Microsoft Fabric can now store reports and semantic models as text in Git, and Fabric workspaces can sync with a repository. The technology is there. The harder question is organisational: whose repository is it, and how do people get in and out?
My answer comes down to four rules.
Rule 1: The client owns everything - suppliers are guests
The repository lives in an Azure DevOps organisation (or GitHub) connected to the client’s own Microsoft Entra tenant. Not in the supplier’s account, not in mine.
External developers join as B2B guests: they sign in with their own company account, the client’s tenant decides what they can see. When the contract ends, the client removes them - the repository, its history and every decision recorded in it stay where they belong.
The tempting alternative - “we’ll host it, it’s simpler” - turns the supplier into the owner of the client’s reporting history. That’s convenient until the day it isn’t.
Rule 2: Access through groups, never through individual people
Two security groups in Entra ID, for example:
| Group | Role in Azure DevOps |
|---|---|
SG-ADO-<PROJECT>-Admins |
project administrators |
SG-ADO-<PROJECT>-Contrib |
developers with write access to the repo |
In Azure DevOps, a group rule ties each group to a licence level and a project role. A guest added to the group gets the right licence and the right permissions automatically on first sign-in. Nobody hands out rights to individual people.
| Onboarding | Offboarding | |
|---|---|---|
| Steps | invite the guest, add to the group | remove from the group |
| Licence and role | granted by the group rule | no longer granted by the rule |
| Who can do it | anyone managing the group | anyone managing the group |
That last row matters. Onboarding and offboarding become an identity task anyone in the client’s IT can do - not a DevOps task only one person understands.
Licences are a smaller question than people expect: the first five Basic users in an Azure DevOps organisation are free, and developers with a Visual Studio subscription bring their own access.
Rule 3: Nobody writes directly to main
main is what’s in production. A branch policy on main means every change arrives through a pull request: someone else sees it, it has a description, it can be reverted as one unit. Squash merge keeps the history readable - one commit per change, not twenty “fix”, “fix 2”, “final”.
With several suppliers this is not bureaucracy. It’s the only place where supplier A sees what supplier B just changed in the shared semantic model - before it breaks A’s report.
Rule 4: The Fabric workspace follows main - it doesn’t write to it
developer laptop ── branch ── pull request ──► main ──► Fabric workspace (sync from Git)
▲
optional: dev workspace ── own branch ──┘ (pull request, like everyone else)
A production workspace connected to main only pulls changes. If people also need to edit directly in Fabric, they get a separate workspace connected to its own branch, and their changes reach main by pull request like everyone else’s.
That makes “what’s in production” a question with a single answer: whatever is in main.
The traps worth knowing in advance
Guests and MFA. A guest signs in with multi-factor authentication in their home tenant. Unless the client’s tenant is set to trust that MFA (cross-tenant access settings), the guest may be asked to do it again - or blocked by a conditional access policy written only with employees in mind. Check conditional access before inviting anyone.
The guest’s home tenant can say no. Some companies block their employees from accepting invitations to other tenants. The invitation then fails on the supplier’s side, not the client’s. Better found out in week one than on the day of the deadline.
Azure DevOps has its own switch for guests. The organisation policy for external guest access must be on, otherwise a correctly invited guest still can’t get in.
One laptop, two identities. A consultant often works for several clients from one machine, so the Git credential manager holds several accounts. Without care, commits go out under the wrong one. Per-repository Git identity and an explicit account binding solve it - but it has to be set up deliberately.
Admins may be able to bypass branch policies. Whether organisation owners can push straight to a protected main is worth checking explicitly. If they can, “nobody writes directly to main” has an exception you should know about.
Run it yourself first
I don’t propose a set-up to a client that I haven’t run myself. This model ran first in a lab in my own tenant - me as administrator, one of my other accounts as the external guest - and then went live in a client’s organisation. The lab is where the awkward questions get answered before anyone else depends on them:
| Question | Why it matters |
|---|---|
| How long from “added to the group” to working access? | Day one of a new supplier |
| How long after removal does access really disappear? | The last day of a contract |
| Does the branch policy stop organisation owners too? | Whether the rule has an exception |
What happens when Fabric tries to commit to a protected main? |
Whether the workspace set-up holds |
| Does the credential manager keep two identities apart? | Consultants with several clients |
The step-by-step set-up, with the commands, is in a separate note: Azure DevOps for Power BI with external developers.
The short version
Version control for Power BI is not mainly a tooling decision. It’s an ownership decision. Put the repository in the client’s tenant, manage people through groups, protect main, and let Fabric follow it. The rest is configuration.
[->] next step
Where do your numbers stop adding up?
Start with a short call. Bring one report nobody trusts - I'll trace it back to where the data gets captured.