AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Ensure Pipelines Host

skill-microsoft-power-platform-skills-ensure-pipelines-host · by microsoft

>-

No reviews yet
0 installs
24 views
0.0% view→install

Install

$ agentstack add skill-microsoft-power-platform-skills-ensure-pipelines-host

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-microsoft-power-platform-skills-ensure-pipelines-host)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Ensure Pipelines Host? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

> Plugin check: Run node "${PLUGIN_ROOT}/scripts/check-version.js" — if it outputs a message, show it to the user before proceeding.

ensure-pipelines-host

> Scope: When no host is bound to the source env, this skill detects any existing host (Custom or PE) for reuse, or — in NoHost state — offers three provisioning paths: a new Platform Host (recommended; idempotent, ~3–5 min); a new Custom Host (admin-only, ~5–10 min); or PPAC manual provisioning (fallback). Implementation details — endpoint names, template names, BAP audience — live in Phase 4.0 / 4.A / 4.C below; user-facing prose stays focused on outcomes.

Power Platform Pipelines need a host environment — a Dataverse environment with the Power Platform Pipelines managed solution installed, where pipelines, stages, run history, and artifacts live. The existing setup-pipeline and deploy-pipeline skills assume a host is already configured. This skill closes that gap.

What we know (sources of truth)

This plan is grounded in three primary sources, in priority order:

  1. useGetOrCreatePlatformEnvironment.v4.ts (Microsoft-internal client source — power-platform-ux/packages/powerapps-appdeployment-ux/src/hooks/v4/). Defines the exact HTTP contract for Platform Environment provisioning: endpoint, body, headers, polling.
  2. ProjectHostProvider.tsx (same repo, src/components/ProjectHostProvider/). Defines the exact resolution order the Power Apps UI uses to determine which environment is the project host for a source environment. We mirror that order so this skill agrees with the UI.
  3. eng.ms createcustompipelineshost (Microsoft-internal). Documents the Custom Host fast-path: a D365_ProjectHost org template that ships the Pipelines app pre-installed, callable through the standard environment-creation API.

Public Microsoft Learn (learn.microsoft.com/power-platform/alm/{platform-host-pipelines, custom-host-pipelines, set-a-default-pipelines-host}) is the user-facing description of the same flows; we cite it for behaviors users will recognize. HARs in PipelinesDeployScenario.har and Pipelines.har confirm the read-side calls.

Three host shapes the tenant can be in

| Shape | How it got there | Where it lives | Org template | |---|---|---|---| | Platform Host (PE) | Auto-provisioned by getOrCreate BAP call (or as a side-effect of first navigation to the Pipelines page in make.powerapps.com). Hidden from the env picker. One per tenant. | Microsoft-managed Dataverse env in tenant's home geo | D365_1stPartyAdminApps | | Custom Host | Created by an admin via PPAC Deployments → New custom host, or via the standard env-create API with the D365_ProjectHost template, or by installing the Power Platform Pipelines app on an existing Dataverse env. | A regular Dataverse env in the tenant | D365_ProjectHost (or app-installed-onto-existing-env) | | No host bound to source env | Tenant has not used Pipelines from this env. | — | — |

The current discover-pipelines-host.js only checks the tenant-level DefaultCustomPipelinesHostEnvForTenant setting. That's one signal of many. This skill implements the full resolution order.

Resolution order (mirrors ProjectHostProvider.tsx)

This is the load-bearing decision tree. It is what the Power Apps UI does. We replicate it so the skill agrees with the UI.

┌─────────────────────────────────────────────────────────────────────┐
│ 1. GetOrgDbOrgSetting('ProjectHostEnvironmentId') on source env     │
└──────────────────────────┬──────────────────────────────────────────┘
                           │
            ┌──────────────┴───────────────┐
            │ value present                │ value empty
            ▼                              ▼
┌───────────────────────┐         ┌────────────────────────────┐
│ 2. Resolve env via    │         │ 5a. Tenant-wide search:    │
│    BAP GET            │         │   list envs + per-env      │
│    /environments/{id} │         │   /deploymentpipelines     │
└───────┬───────────────┘         │   probe.                   │
        │                         │                            │
   environmentSku?                │   - 1 Custom Host found →  │
        │                         │     AvailableUnboundCustom │
   ┌────┴────────────┐            │     (3.C-pre)              │
   │ Platform        │            │   - >1 Custom Hosts →      │
   │                 │            │     MultipleUnboundCustom  │
   │                 │            │     (3.C-pre')             │
   │                 │            │   - PE only →              │
   │                 │            │     PlatformHostExists-    │
   │                 │            │     Unbound (3.C-pre'')    │
   │                 │            │   - none → NoHost (3.C)    │
   │                 │            │                            │
   │                 │            │ 5b. Decision tree paths    │
   │                 │            │   for create-new (3.C):    │
   │                 │            │   - Platform getOrCreate   │
   │                 │            │     (fast-path, no admin)  │
   │                 │            │   - Custom D365_ProjectHost│
   │                 │            │     (fast-path, admin)     │
   │                 │            │   - Manual app install     │
   │                 │            │   - Manual PPAC create     │
   │                 │            └────────────────────────────┘
   ▼                 │
┌──────────────┐     │
│ 3. Check     │     │ environmentSku ≠ Platform (Custom Host)
│  Default-    │     ▼
│  Custom-     │   ┌──────────────────────────────┐
│  Pipelines-  │   │ 4. Use the Custom Host       │
│  HostEnv-    │   │    directly. Skip default-   │
│  ForTenant   │   │    custom check.             │
└──────┬───────┘   └──────────────────────────────┘
       │
   ┌───┴────────────────────────┐
   │ admin set a custom default │
   │                            │
   ▼                            ▼
┌─────────────────┐  ┌─────────────────────────┐
│ default ==      │  │ default !=              │
│ org setting?    │  │ org setting             │
│                 │  │                         │
│ → use default   │  │ → CannotRedirect ERROR  │
│   custom        │  │   (user locked to PE    │
└─────────────────┘  │   but admin overrode    │
                     │   at tenant scope)      │
                     └─────────────────────────┘

   if no admin default → use PE

Source: ProjectHostProvider.tsx lines 100–213 (orgSetting fetch → defaultCustomPipelinesHost fetch → finalProjectHostEnvironmentId resolution).

What this skill does NOT do

These are deliberate non-goals (each based on a hard constraint or a destructive blast-radius — see Design Constraints below):

  • Does not silently provision anything. Any action that creates an env or binds the source env to a host requires explicit user confirmation, with the tenant name + tenant ID echoed back. PE is tenant-singleton and admin-non-deletable, so the Phase 4.0 pre-call confirmation gate is the principal mitigation against wrong-tenant provisioning. The getOrCreate endpoint is idempotent — calling it on a tenant that already has a PE returns the existing one rather than creating a duplicate.
  • Does not call Force Link to rebind an environment to a different host. Force Link is destructive (makers lose access to existing pipelines in the previous host) and is hidden behind a separate confirmation gate, only reachable when the user explicitly says "rebind".
  • Does not change the tenant-level DefaultCustomPipelinesHostEnvForTenant setting. That setting is irreversible-adjacent (existing pipelines in the previous default become inaccessible — see learn.microsoft.com/power-platform/alm/set-a-default-pipelines-host). Out of scope.
  • Does not delete environments.
  • Does not write ProjectHostEnvironmentId directly. Binding is established through the documented Pipelines flow (creating a deploymentenvironment record in the host); writing the org setting directly bypasses validation.

Auth strategy: PAC-first with BAP fallback (--source auto)

Read-side detection (Phase 2 resolution order, env list, env-by-id) defaults to --source auto:

  1. If a BAP token is provided, try BAP env-list / env-GET first (richer data including lastModifiedTime, permissions, tenantId).
  2. On HTTP 401 or 403, fall back to pac admin list --json via pac-bap-shim.js. PAC has its own first-party client-ID grants on BAP that Az CLI doesn't always inherit (verified 2026-04-28: D365DemoTSCE53051106 demo tenant rejects Az tokens for BAP even with correct audience claims).
  3. If no BAP token is provided at all, go straight to PAC.

The PAC shim returns BAP-shaped data; downstream code (sku filter, ranking, classification) is unchanged. Fields not provided by PAC (tenantId, lastModifiedTime, permissions, isManaged) come back as null — none are critical for host detection. PAC also doesn't surface Platform Hosts (PE) since pac admin list doesn't include Platform-sku envs; PE detection requires --source bap with a working BAP token.

Write-side actions (env-create POST in provision-custom-host.js, lifecycle op polling) still require BAP. Az CLI tokens with the right audience usually work for these even when env-list calls fail, because the BAP RP enforces different policy on actions than reads. If provision-custom-host.js returns 401, the user must register a service principal in the target tenant (or use the PPAC UI fallback path 4.C).

Design Constraints

  1. JIT provisioning is required when a PE is selected — existing or freshly provisioned. From ProjectHostProvider.tsx (line 232–240 comment): "In the Platform Environment case, the user may not already be provisioned there, so BAP cannot discover it. So we'll use the org URL we retrieve from the getOrCreate call to make this first request so that user JIT can be triggered." When Phase 2 detects an existing PE and the user accepts it (Phase 3.A) — or when Phase 4.0 provisions a new PE via getOrCreate — Phase 5's WhoAmI call against instanceApiUrl triggers JIT before any subsequent host op. (For Custom Host paths the caller has access by construction.)
  2. CannotRedirect is a real terminal state, not a theoretical edge case. It happens when ProjectHostEnvironmentId (org setting on source env) points at PE but DefaultCustomPipelinesHostEnvForTenant (admin tenant setting) points elsewhere. The skill must detect this and surface it as a specific error — falling through silently would route pipeline ops at the wrong host.
  3. Admin-only Custom Host fast-path. PPAC's New custom host flow is gated by DeploymentHubCreatePipelinesHostForAdminsOnly and shows only for Global / Power Platform / Dynamics admins (eng.ms doc). The BAP env-create API also needs the equivalent privilege. Non-admins get 403; the skill preflight-attestation-prompts and gracefully falls back to manual paths.
  4. 404 from BAP env GET is ambiguous. Returns 404 for deleted, disabled, no-PE, and no-access without distinguishing (PowerPipelines_PE_Knowledge.md §6.A). We never treat a single 404 as "no host exists" — we corroborate via list-environments and the org setting before acting.
  5. Each environment is bound to only one host at a time. Rebinding requires Force Link, which is destructive in the previous host. Out of scope (see non-goals).
  6. The skill runs in user OAuth context — same scope and audience the Power Apps UI uses. BAP calls use https://service.powerapps.com/ audience.

> Idempotency of getOrCreate — the BAP getOrCreate endpoint is idempotent (existing PE returns 200 + provisioningState === 'Succeeded'; new PE returns 202 + lifecycle op). Phase 4.0 leverages this — calling getOrCreate on a tenant that already has a PE is safe and just returns the existing one. The provision-platform-host.js helper surfaces the distinction via an alreadyExisted: true | false flag in its return value (recorded in the docs/alm/last-host-check.json telemetry block as platformHostAlreadyExisted).

Prerequisites

  • PAC CLI logged in (pac env who succeeds)
  • Azure CLI logged in (az account show succeeds)
  • A source Dataverse environment URL (read from powerpages.config.json if invoked from a Power Pages project; passed as arg otherwise)
  • For Phase 4 admin-only paths: caller has Global / Power Platform / Dynamics admin (skill detects and surfaces 403 cleanly if missing)

Phases

Phase 1 — Detect prerequisites and gather tenant context

Create all tasks upfront at the start of this phase.

Tasks to create:

  1. "Check local cache and detect prerequisites"
  2. "Run resolution order to find host"
  3. "Confirm action with user"
  4. "Execute chosen path"
  5. "JIT-provision and verify host"
  6. "Write host-check artifact"

Steps:

  1. Local cache fast-path. If docs/alm/last-host-check.json exists AND `Date.now() - Date.parse(checkedAt) 🚦 Gate (consent · ensure-pipelines-host:1.4.tenant-identity): Echo tenant display name + tenant GUID + dev env URL before any host detection. First of the wrong-tenant guards. Cancel exits cleanly before any BAP/Dataverse call.
  1. Tenant identity confirmation gate. Echo back via AskUserQuestion:

> "About to inspect Pipelines host configuration for tenant {TENANTDISPLAYNAME} ({tenantId}), org {organizationId}, dev env {devEnvUrl}. Continue? 1. Yes / 2. Cancel"

(When TENANT_DISPLAY_NAME is null, drop the bold tenant-name segment and lead with the tenant GUID.)

First of the consent gates that guard against wrong-tenant operations.

Phase 1.5 — Ground in current Pipelines host documentation

> Reference: ${PLUGIN_ROOT}/references/alm-docs-grounding.md

Cap this step at ~30 seconds. If MCP search / fetch errors out, log a one-line note and continue — this skill must remain runnable offline.

  1. Run microsoft_docs_search with the query: Power Platform Pipelines host environment Platform Host Custom Host.
  2. Fetch https://learn.microsoft.com/en-us/power-platform/alm/pipelines (and at most one sister page on host setup, default-custom-host configuration, or admin role requirements) in parallel via microsoft_docs_fetch.
  3. Extract a one-paragraph summary of what Microsoft Learn currently says about Platform vs Custom Host trade-offs, the resolution order (org-db setting → BAP env metadata → tenant default), and admin role requirements. Compare against this skill's own Resolution order section and ${PLUGIN_ROOT}/references/cicd-pipeline-patterns.md; flag any divergence (e.g. new Platform-Host SKU, changed default-custom-host setting name, new tenant policy controls).
  4. Use the summary to inform Phase 2+ decisions. Do not silently change skill behavior — surface any divergence to the user as a soft warning before Phase 3 (Confirm action with user).

Phase 2 — Run resolution order to find host

This phase is read-only. It produces a RESOLUTION object the user-confirm phase branches on.

The phase mirrors ProjectHostProvider.tsx exactly. The useState variables in that hook map to fields in our RESOLUTION:

| TS variable | Our field | |---|---| | orgSetting.orgDbOrgSettingValue | orgSettingHostEnvId | | initialProjectHostEnvironmentId | (same) | | isInitialHostPlatformEnvironment | isPlatform | | defaultCustomPipelinesHost | tenantDefaultCustomHostEnvId | | finalProjectHostEnvironmentId | finalHostEnvId | | projectHostStatus | status |

Steps:

  1. Org-setting probe (mirrors useGetOrgDbOrgSetting('ProjectHostEnvironmentId') line 103 in tsx). New helper check-env-host-binding.js:

`` POST {devEnvUrl}/api/data/v9.0/GetOrgDbOrgSetting Authorization: Bearer {DEV_TOKEN} Body: { "SettingName": "ProjectHostEnvironmentId" } ``

  • Empty SettingValue → no current binding. Skip to S

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.