Partner Center Bridge
Open source · self-hosted · v0.4.0

Cross-tenant Microsoft 365 ops,
done the same way every time.

A self-hosted bridge over Microsoft Graph and the Partner Center API for MSPs. Declare desired state once and reconcile every customer tenant to it - and fix the tickets your queue sees every week with transparent Diagnose - Fix - Verify workflows.

ASP.NET Core 8 React + Vite + TS PostgreSQL Microsoft Graph Partner Center v3 Exchange Online V3
What's real today

Honest maturity, feature by feature.

No roadmap theatre. Here is what ships in the current build and how far along each piece is.

Stable Win32 apps, every tenant

Upload an .intunewin template once; the bridge runs the full documented Intune beta upload state machine per tenant and fans a new content version out to everyone on the contract.

Stable Hire & offboard by contract

Contract-driven provisioning: usage location, licenses, groups, UPN convention. New hires and terminations become one reviewed action with a per-step result, not a checklist.

Beta Known-fix workflows

MFA reset, password reset, compromised-account lockdown, and license repair - each one diagnoses transparently, fixes idempotently, then re-diagnoses to prove it worked.

Beta Mailbox archive repair

The "mailbox full / not archiving" fix that replaces a ~10-cmdlet Exchange Online dance, run through the EXO PowerShell V3 module out-of-process with an app-only certificate.

Stable Find a user anywhere

Search every active tenant at once and jump straight from a person to a fix - start from the human on the phone, not the portal.

Beta Self-registration, passkeys & TOTP

Run without an external IdP: open registration, WebAuthn passkeys as the primary sign-in, TOTP with recovery codes, and per-tenant sharing where an Owner grants Viewer/Operator/Owner access - no admin bypass.

Beta Config snapshots: diff & git sync

Point-in-time backups of Conditional Access, Named Locations, and Device Compliance Policies, diffable section-by-section or whole-tenant, exportable as a workbook, and optionally mirrored to a real git repo.

Planned Two-way LDAP sync

Phase 4. The abstractions are scaffolded but the sync itself is not implemented yet. It is on the list, not in the build - and this page will say so until it is.

Current app

Fresh screenshots from the React SPA.

Generated from the live web client with mocked API data by docs/scripts/capture-product-media.mjs, so the Pages site always shows the current UI without needing a live backend or a real tenant.

DashboardOne local-only triage view: tenant and deployment counts, what needs attention (failed deploys, missing GDAP, failed runs), and the recent run log - fast enough to hit on every page load.
Diagnose before you touch anythingEvery workflow shows its findings verbatim first - sizes, archive state, retention policy, and the hidden blockers - with Ok / Info / Warning / Blocker status on each check.
Deploy fan-outPick a packaged template, check the target tenants, and push. Each tenant reports its own status and Intune app id; pushing a new version is how "update everyone" works.
Person-first Find UserSearch all active tenants at once. Each hit carries MFA reset, password reset, lockdown, and license repair; unreachable tenants are listed honestly, not hidden.
Tenants and contractsSync your customer list from Partner Center, see delegation status at a glance, and assign each tenant to the contract whose desired state it should follow.
Passkey-primary sign-inNo external IdP required: register an account, tap a passkey to sign in - no email typed first - with password and TOTP as fallbacks. See Authentication.
Config snapshots & diffPoint-in-time backups of Conditional Access, Named Locations, and Device Compliance Policies - diffed section-by-section, exportable as a patch. See Config Snapshots.
The honest loop

Diagnose → Fix → Verify.

Every workflow follows the same shape, and every run is recorded - who ran what, against which tenant, with which findings. Ticket notes write themselves.

1 DIAGNOSE

Read the real state from Graph or Exchange Online and show every finding verbatim: Ok Info Warning Blocker. Nothing changes yet.

2 FIX

Apply the known remediation step by step, recording each step's success or failure. Steps are idempotent - re-running is always safe, and for the async mailbox move, re-running is the nudge.

3 VERIFY

Re-diagnose immediately and show the post-fix state, so "it should be fixed now" becomes "here is the state that proves it" - persisted to Postgres as ticket-ready evidence.

Why it's different

Non-invasive, transparent, auditable, self-hosted.

Non-invasiveNo agents in customer tenants

The bridge speaks the same Graph and Partner Center APIs Microsoft's own portals use, under the Secure Application Model and per-customer GDAP consent. Nothing is installed downstream.

TransparentNothing happens behind your back

Diagnoses are shown raw. Remediation steps are listed one by one with their outcome. Reconcile plans are previewed as a dry run before anything deploys.

AuditableEvery run is evidence

Workflow runs persist to Postgres with operator identity, inputs, findings, and steps. Failures can push a Teams Adaptive Card or plain JSON to a webhook.

Two auth planesWho you are vs. what the bridge may do

Operators authenticate via your own OIDC provider, or self-registered local accounts with passkeys and per-tenant sharing - no IdP required. The Microsoft plane is a separate SAM app with an encrypted, auto-rotating refresh token.

Contract modelDesired state, reconciled

A contract is a named desired state shared by a set of tenants. The reconcile engine produces a deploy / update / nothing plan you review before it runs.

Self-hostedYour credentials stay yours

Docker Compose for evaluation, Kubernetes (Kustomize + Flux + SOPS) for production. Secrets are encrypted at rest via ASP.NET Data Protection.

Integrations

The Microsoft surfaces MSPs actually live in.

Tags reflect real delivery status in the current build - not intentions.

CoreMicrosoft Graph

Per-tenant clients via GraphTenantClientFactory, powering Intune, users, groups, licenses, and the Identity workflows.

StablePartner Center v3

Customer list sync and the Secure Application Model token flow via SamTokenService (MSAL), with automatic refresh-token rotation.

StableIntune Win32 apps

The full .intunewin upload state machine: content version, chunked block-blob upload, commit with parsed encryption info, then assign.

BetaExchange Online V3

Mailbox configuration Graph can't do, through the EXO PowerShell module (app-only certificate) run out-of-process via PwshRunner.

StableAuthentik / OIDC

Operator sign-in as a JWT bearer plane. Any standard OIDC provider works; set Auth and the matching VITE_OIDC_* vars.

StableTeams / webhook alerts

Failed runs push an Adaptive Card to a Teams incoming webhook, or plain JSON to any receiver - configured in the Notifications section.

CorePostgreSQL

The local source of truth via EF Core: tenants, contracts, templates, deployments, and full workflow run history.

PlannedTwo-way LDAP

Phase 4. Scaffolded for, not implemented. Directory sync back to on-prem is on the list but not in the build.

Try it in two minutes

Click through the whole UI with auth disabled.

Compose runs Postgres, the API, and the SPA with auth off, so you can explore every screen without an identity provider. Reaching real customer tenants additionally needs a partner Entra app and a one-time SAM bootstrap.

Operator plane - the SPA + API authenticate you via OIDC (JWT bearer). The operator's name from the token is what lands in run history.
Microsoft plane - a multi-tenant Entra app under the Secure Application Model. SamTokenService exchanges the stored, encrypted, auto-rotated refresh token for a per-tenant Graph token on demand.
Reconcile engine - Core compares each contract's desired state against what a tenant actually has and produces a plan you approve before it runs.
# Clone and run the local stack
git clone https://github.com/Spillers-Technology/PartnerCenterBridge.git
cd PartnerCenterBridge
docker compose up --build

# SPA:  http://localhost:8082  (auth disabled in compose)
# API:  http://localhost:5080  (Swagger at /swagger)

# Or run the pieces directly
dotnet run --project src/PartnerCenterBridge.Api
cd web && npm install && npm run dev

# Tests need no tenant - orchestration runs against WireMock
dotnet test

Run it on your own stack.

Free and open source under MIT, with Docker Compose, Kubernetes manifests, and docs that now match the current build. Need it built out or wired into the rest of your stack? Spillers Technology does that.