
Dv Solution
Package and move Dataverse customizations across dev, test, and prod using PAC CLI export/import plus Python SDK post-import validation.
Overview
dv-solution is an agent skill most often used in Build (also Ship launch, Operate infra) that manages Dataverse solution create, export, import, promotion, and post-import validation via PAC CLI and the Python SDK.
Install
npx skills add https://github.com/microsoft/dataverse-skills --skill dv-solutionWhat is this skill?
- Full solution lifecycle: create, export, unpack, pack, import, validate
- Python SDK for publisher and solution records—avoid raw HTTP for those tables
- Publisher customizationprefix is permanent for existing schema names
- Explicit boundaries: use dv-metadata, dv-data, dv-query, dv-connect for other needs
- Post-import validation via Python SDK after PAC deployments
Adoption & trust: 31 installs on skills.sh; 136 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You customized Dataverse in dev but lack a repeatable, validated path to deploy that solution to test or production.
Who is it for?
Solo Power Platform builders shipping controlled solution promotions between dev, test, and prod.
Skip if: One-off record edits, ad-hoc queries, or greenfield table design—use dv-data, dv-query, or dv-metadata instead.
When should I use this skill?
User wants to package customizations, deploy to another environment, or move work between dev, test, and prod.
What do I get? / Deliverables
You produce importable solution packages, promote across environments with PAC, and confirm health with SDK validation after import.
- Exported and importable Dataverse solution packages
- Publisher and solution records created via SDK
- Post-import validation report for the target environment
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Solution lifecycle is integration work during build, then repeats in ship and operate when promoting environments. PAC-driven solution create/export/import sits in integrations alongside metadata and data skills in the Dataverse family.
Where it fits
Create a publisher with a permanent prefix and a new solution before metadata work lands in dv-metadata.
Import a packed solution into a pre-prod environment ahead of go-live cutover.
Re-export after hotfixes and validate import health in production-aligned sandboxes.
How it compares
Dataverse solution packaging skill—not generic CRM scripting or frontend SaaS scaffolding.
Common Questions / FAQ
Who is dv-solution for?
Indie consultants and builders using Microsoft Dataverse who package customizations and move them across environments with PAC CLI.
When should I use dv-solution?
When you want to create/export/import solutions, promote dev to test or prod, or validate post-import— not when only querying records or editing table metadata.
Is dv-solution safe to install?
Review Security Audits on this page; imports change production metadata and data boundaries—test in non-prod first.
Workflow Chain
Requires first: dv connect
Then invoke: dv metadata
SKILL.md
READMESKILL.md - Dv Solution
# Skill: Solution Create, export, unpack, pack, import, and validate Dataverse solutions via PAC CLI. Includes post-import validation using the Python SDK. ## Skill boundaries | Need | Use instead | |---|---| | Create tables, columns, relationships, forms, views | **dv-metadata** | | Create, update, or delete data records | **dv-data** | | Query or read records | **dv-query** | | Connect to Dataverse / set up MCP | **dv-connect** | --- ## Create a New Solution **Use the Python SDK for publisher and solution record creation — not raw HTTP.** Publishers and solutions are standard Dataverse tables. `client.records.create()` and `client.records.get()` handle auth, pagination, and error handling automatically, avoiding the URL encoding, header boilerplate, and GUID-parsing bugs that raw `urllib` calls introduce. ### Step 1: Find or Create the Publisher Every solution belongs to a publisher. The publisher's `customizationprefix` (e.g., `contoso`, `sa`, `lit`) is prepended to every custom table, column, and relationship schema name. **This prefix is effectively permanent** — existing components keep their prefix forever, even if you change the publisher later. **Never use the default `new` prefix.** It provides no organizational identity, risks naming collisions, and signals the developer did not follow best practices. **Discovery flow — always run this before creating a publisher:** ```python import os, sys sys.path.insert(0, os.path.join(os.getcwd(), "scripts")) from auth import get_client # get_client sets a plugin attribution context on the User-Agent header. # Do not modify the context value — it is a closed schema for server-side # telemetry (app/skill/agent). Never include secrets or PII. client = get_client("dv-solution") # 1. Query for existing non-Microsoft publishers pages = client.records.get( "publisher", filter="customizationprefix ne 'none' and uniquename ne 'MicrosoftCorporation' and uniquename ne 'Microsoftdynamic'", select=["publisherid", "uniquename", "friendlyname", "customizationprefix"], top=10, ) publishers = [p for page in pages for p in page] if publishers: # Show existing publishers and ask user which to use print("Existing publishers in this environment:") for p in publishers: print(f" {p['uniquename']} (prefix: {p['customizationprefix']}_)") # ASK THE USER: "Which publisher should this solution use?" # Or: "Should I reuse '<name>' (prefix: <prefix>_)?" publisher_id = publishers[0]["publisherid"] # after user confirms else: # No custom publisher exists — ASK THE USER for prefix # "What publisher prefix should I use? (e.g., 'contoso', 'sa', 'lit' — 2-8 lowercase chars)" publisher_id = client.records.create("publisher", { "uniquename": "<publisheruniquename>", "friendlyname": "<Publisher Display Name>", "customizationprefix": "<prefix>", # from user input, NOT 'new' "description": "<description>", }) ``` **Rules:** - **Always ask the user** before creating a new publisher or choosing a prefix. Never hardcode a prefix. - The prefix must match any tables already created in the solution — you cannot mix prefixes. - One publisher can own many solutions. Reuse an existing publisher when possible. ### Step 2: Create the Solution Record Use the SDK to create the solution record (preferred over raw Web API): ```python import os, sys sys.path.insert(0, os.path.join(os.getcwd(), "scripts")) from auth import get_client # get_client sets a plugin attribution context on the User-Agent header. # Do not modify the context value — it is a closed schema for server-side # telemetry (app/skill/agent). Never include secrets or PII. client = get_