Skip to main content

add-dataverse

Use when the user wants to add Dataverse tables (existing or new) to a Power Apps mobile app, extend an existing Dataverse table with new columns, or apply an approved data model plan.

Source facts

Repository
microsoft/power-platform-skills
Last source activity
October 9, 2026 at 06:04
Detected SKILL.md language
English
Stars
1,103
Forks
223

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
add-dataverse
description
Use when the user wants to add Dataverse tables (existing or new) to a Power Apps mobile app, extend an existing Dataverse table with new columns, or apply an approved data model plan.
user-invocable
true
allowed-tools
Read, Edit, Write, Grep, Glob, Bash, AskUserQuestion, EnterPlanMode, ExitPlanMode, Task, Skill
model
opus
> **Plugin check**: Run `node "${PLUGIN_ROOT}/scripts/check-version.js"` - if it outputs a message, show it to the user before proceeding. **📋 Shared instructions: [shared-instructions.md](${PLUGIN_ROOT}/shared/shared-instructions.md)** — read first. # Add Dataverse **App root:** before any project read or command, execute [app-working-directory.md](${PLUGIN_ROOT}/shared/references/app-working-directory.md). Use its resolved absolute `working_dir` for every shell call and file tool, including referenced commands and delegated skills; never inherit a prior `cd`. **Entry routing:** use the shared [App feature entry points](../../shared/shared-instructions.md#app-feature-entry-points) preflight before the workflow below. **Invocation scope:** follow [Data-source invocation scope](../../shared/shared-instructions.md#data-source-invocation-scope) before the workflow below. Standalone calls use this skill's own data-delta approval and verification; do not start a full-app plan or screen workflow. An existing plan alone does not mean it includes or approves the new request; never replay the old Data Model instead of resolving the requested delta. **Removal branch:** after resolving invocation scope, `--remove` or an approved app-binding removal executes [data-source-removal.md](../../shared/references/data-source-removal.md), then returns without entering Steps 1-9. Removing a plan row is not implemented by re-running table creation or by deleting Dataverse metadata. For a mixed edit, the owner adds/refreshes first and invokes removal separately after consumer edits. **Refresh branch:** after resolving invocation scope, `--refresh` or an approved service-only refresh executes [Refresh a retained source](../../shared/references/data-source-removal.md#refresh-a-retained-source) and returns before Steps 1-9. Preserve the exact `--data-source-name` and approved binding identity. Do not replay schema writes, publish, or run `add-data-source`. Two paths: - **Existing tables only** — resolve the current scope in Steps 1–2, then skip schema writes and use Step 6 to add only missing approved bindings or refresh approved retained sources. - **New / extended tables** — full workflow with Web API mutations in dependency order ## Workflow 1. Verify project & auth → 2. Resolve plan/operation manifest → 3. Setup Dataverse Web API auth → 4. Validate manifest or reconcile live metadata → 5. Execute sequential metadata phases → 6. Add data sources → 6b. Publish fallback customizations → 6c. Verify tables → 6d. Write manifest → 7. Inspect generated files → 8. Type-check → 8.5. Offline profile reconciliation → 9. Summary --- ### Step 1 — Verify project & auth Confirm Power Apps mobile app: For `--plan-only` or a planning-phase handoff, check the app files read-only and use the shared proposal-only environment-context rule. Use the same non-persisting lookup before approval in a normal invocation. Incomplete or conflicting context returns `NEEDS_CONTEXT` after read-only recovery; never remove the safety flags or redirect output into configuration to make planning succeed. ```bash cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; } if [ ! -f power.config.json ] || [ ! -f app.config.js ]; then echo "BLOCKED: working_dir is not an initialized app" >&2 exit 1 fi node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "<selected-environment-id>" --no-cache --require-tenant ``` Read `<selected-environment-id>` from this app's `power.config.json`. Capture the **environment URL** (for example `https://contoso.crm.dynamics.com`), **environment ID**, and **tenant ID** from the resolver for Step 3. Use the owner's absolute `working_dir` for every command and artifact. ### Step 2 — Resolve plan **Telemetry checkpoint: `resolve_dataverse_schema_plan`** Look for `native-app-plan.md` in the project root: ```bash cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; } test -f native-app-plan.md ``` **Resolve the current request before consuming an existing plan.** A direct standalone invocation must compare its requested tables/columns/service changes with the existing plan and read-only live evidence. Present and approve that exact delta at Step 2.7 after shared planning validation, then save only the accepted plan changes before implementation. If the request adds nothing, verify the existing outcome and report a no-op; do not apply other pending rows. If intent or scope is missing, ask or return `NEEDS_CONTEXT` without mutation. An explicit request to apply the whole existing plan still requires approval of the reconciled operation set. For an approved child call, use only the supplied current `approved_scope`. In either case, `--plan-only` returns the proposal and STOPs before plan saving, approval-receipt creation, service generation, or Steps 3–9; a planning-phase caller has the same proposal-only boundary. Before reading plan content, inspect `$ARGUMENTS` for the five fast-path artifact flags in Step 2a. When all are present, only confirm `native-app-plan.md` exists for hash validation; do not parse its Data Model section or build operations/service lists from Markdown. For all non-fast-path Dataverse proposals from `/setup-datamodel`, `/edit-app`, or a standalone request, including an existing-plan delta, read and execute [dataverse-change-planning.md](../../shared/references/dataverse-change-planning.md). Use its scoped evidence/contract for the diagram, architect, or inline path. An approved child with `planning_snapshot`, `architect_evidence`, and `schema_contract` instead enters Step 2b to verify that supplied scope; it must not rediscover or re-approve it. New-binding requests use this planning path; service-only refreshes and retirements have already returned from their branches. Older callers may not supply the new structured handoff. Do not assume compact evidence or complete approval from the caller's name. Without a complete approved handoff, resolve the current requested delta and use this leaf's normal proposal and Step 2.7 approval path before execution. Resolve required invocation context first; a missing or conflicting child root still returns `NEEDS_CONTEXT` before project access. Never silently replay the saved plan or treat `--skip-planning` as consent. An approved legacy child without compact-planning artifacts keeps the supported Markdown/live-reconciliation path below only when its current request, absolute root, implementation phase, and exact approved delta are all established. Never use this legacy path to bypass a partial or invalid compact-planning handoff, or to skip setup/standalone proposal validation. **Legacy input only, if present and `<operation_manifest_mode> = fallback` without a shared scoped contract:** read the `## Data Model` section. Extract: - The target reconciliation table (`reuse` / `extend` / `create` / `adapt` / `defer` decisions and evidence) - The Mermaid ER diagram (informational) - The "Creation Order" tier list - Every table referenced by `## Screens`, identity resolution, related-entity fields, forms, dashboards, or shared hooks, including standard reused tables such as `systemuser`, `contact`, and `account` For legacy callers without scoped planning artifacts, build `SERVICE_REQUIRED_TABLES` as the union of: 1. every non-deferred row in Target Reconciliation (`reuse`, `extend`, `create`, or `adapt`); 2. every table in Creation Order; 3. every table named by screen/hook data requirements. Keep this full service inventory as retained context. Only the current approved delta and its necessary dependencies enter live schema reconciliation. With a complete approved legacy handoff, proceed to Step 3 after this initialization; do not repeat proposal Steps 2.5–2.7 or require new compact artifacts from that owner. A planning-phase caller still returns without implementation. For the shared scoped path, use the normalized contract's non-deferred `serviceRequired` declarations instead. Keep the broader existing-app service inventory as retained context, not a registration or mutation work list. **Hard rule:** `reuse` means "do not mutate schema"; it does **not** mean "skip generated service." If app code reads or writes a reused table, that table must be in `SERVICE_REQUIRED_TABLES`. Carry forward any `adapt` (auto-renamed) and `defer` (out-of-scope this run) decisions with their recorded reasons, and apply the alias map to every name you use. A data-modelling conflict never halts this skill — it resolves to `adapt` or `defer` and is reported in Step 9. This classification belongs to planning: after approval, a changed decision returns to the owner for revision/approval before any write. For a scoped handoff, restrict schema writes to the exact `approved_scope` delta; unaffected plan rows are context, not permission to replay their mutations. Apply the same restriction to the newly approved standalone request delta. Retain the full required-service set for existing screens. If reconciliation would change an approved name, storage target, or screen contract, return the proposed adaptation to the owner (or standalone user) before writing. Report dependent consumer changes for separate approval; do not silently rename underneath the app or treat data approval as permission to edit screens. **If absent:** check `$ARGUMENTS` for diagram hints (`*.png`, `*.jpg`, `*.jpeg` filename, `erDiagram` keyword, `||--o{` cardinality syntax). - **Diagram hint present** → Path A (Step 2.5). - **No hint AND `$ARGUMENTS` describes what the app does** (the typical case) → silently take Path B (Step 2.6 — spawn architect). No prompt. - **No hint AND `$ARGUMENTS` is empty / non-descriptive** → only then prompt with `AskUserQuestion`: > "How would you like to define the data model? > (a) I have an existing ER diagram to upload (PNG/JPG path, Mermaid syntax, or text description) > (b) Let the data-model-architect agent analyze and propose one (default) > (c) Cancel — I'll plan it elsewhere first" Recommend (b), but wait for an explicit answer. Empty input is not approval; cancellation stops the workflow without planning or mutation. A supplied description may select the read-only architect path, not approve its result. With an existing plan and a new request, take the same diagram or architect/ inline proposal path for only that delta, then Step 2.7. Do not skip validation because a saved plan exists. #### Step 2a — Approved operation-manifest fast path When `$ARGUMENTS` supplies all five paths below, record `<operation_manifest_mode> = candidate`: - `--schema-contract <working_dir>/.tmp/dataverse-schema-contract.json` - `--approval-receipt <working_dir>/.tmp/mobile-plan-status.json` - `--execution-reconciliation <working_dir>/.tmp/dataverse-execution-reconciliation.json` - `--operation-manifest <working_dir>/.tmp/dataverse-operation-manifest.json` - `--publish-checkpoint <working_dir>/.tmp/dataverse-publish-pending.json` Do not reconstruct tables, columns, relationships, keys, payloads, tiers, or service requirements from Markdown on this path. The gate-owned approval receipt binds the exact structured contract content/hash, final plan hash, and final screen/service dependency list; `native-app-plan.md` remains the human review artifact. An entirely absent fast-path handoff means `<operation_manifest_mode> = fallback` and preserves the standalone workflow below, beginning with Step 2 initialization. A partially supplied handoff, or a supplied manifest/contract/reconciliation/checkpoint that is malformed, stale, incomplete, or bound to different context/files, must fail closed: print the exact validation errors and return control to the orchestrator. Never jump to Step 4 without Step 2 initialization, partially trust a candidate, or mix its operations with agent-derived operations. For an approved implementation candidate, continue to Step 3 and the existing Step 3c manifest validation; skip Steps 2b and 2.5–2.7. Supplied execution artifacts never override `--plan-only` or a planning-phase caller: those calls return the proposal without entering Step 3. #### Step 2b — Approved scoped planning context Enter only for a shared compact-planning handoff, not an approved legacy child or a creation fast-path candidate. The data owner passes the absolute `planning_snapshot`, `architect_evidence`, and `schema_contract` paths plus accepted operations, `contract_sha256`, and `plan_sha256` in `approved_scope`. Require all fields and real implementation approval; partial, missing, changed, or mismatched context returns `NEEDS_CONTEXT` to the owner, never a fallback to whole-plan replay or fresh approval inference. Before Step 3, compare SHA-256 of the contract and final plan file bytes with those frozen approval hashes, verify the selected target identity, and run the shared compact-evidence and decision validators against the supplied artifacts. Do not overwrite either hash to accept changed files. Read mutation intent from the normalized scoped contract, not historical Markdown rows; retain unaffected generated services. A proposal-only caller returns without mutation. After success, keep `<operation_manifest_mode> = fallback` for the existing standalone execution/reconciliation path, skip Steps 2.5–2.7, and proceed to Step 3. Planning evidence is not fresh write evidence: Step 4 still reconciles only this accepted delta and its required dependencies against the live target. Do not fabricate a `create-mobile-app` receipt or partially supply Step 2a flags. ### Step 2.5 — Path A: Parse user-provided diagram Used when the user has an existing diagram from another tool (Visio, dbdiagram.io, screenshot, hand-drawn). Accept three input formats: | Format | How | |---|---| | **Image path** (`*.png` / `*.jpg` / `*.jpeg`) | Use `Read` on the file path. The vision-capable model extracts entities, columns, relationships. | | **Mermaid syntax** | User pastes a `erDiagram` block in chat. Parse the entities, columns, and `\|\|--o{` cardinalities directly. | | **Text description** | Parse the requested entities/relationships as intent, then use the shared snapshot-only architect handoff with the text and scoped compact evidence. | Whichever format, normalize into the same structure used by the planner agent: ```yaml publisherPrefix: <from detected publisher prefix or user> tables: - logicalName: contoso_servicevisit displayName: Service Visit status: new # new | extend | reuse columns: [...] relationships: [...] ``` Then follow the shared planning workflow to generate `_dm_section.md` with the Mermaid diagram and a normalized `.tmp/dataverse-schema-contract.json` from compact evidence. Run its decision validation for the diagram just as for an architect result, then continue to Step 2.7. Do not save the live plan here. ### Step 2.6 — Path B: Spawn architect agent If the user picked Path B, use the shared workflow's `mobile-app:data-model-architect` handoff with `Dataverse planning mode: required`, the absolute snapshot/compact-evidence paths, the scoped request, and planning/ proposal-only context. Require `_dm_section.md` and the normalized contract. If the host cannot spawn agents, produce both inline from that same evidence. Use the shared structured-signal recovery before generic retries. A diagram parse failure requires resolving the intended entities, not silently inventing a replacement model. If they need new tables and refuse both paths, recommend `/setup-datamodel` for data-only planning and stop. Do not start another workflow without a new request. ### Step 2.7 — Validate and approve the standalone delta For every new standalone proposal, require exit `0` from `validate-dataverse-planning-decisions.js` for the current normalized contract and snapshot before presenting the existing approval gate. This includes diagrams, architect results, inline fallbacks, and edits to an existing plan. If either `--plan-only` or a planning-phase caller applies, return the validated proposal and STOP before saving the live plan or granting execution permission. Otherwise show the exact delta and its concerns with `EnterPlanMode`. Approval saves only that delta into `native-app-plan.md`, preserving unaffected sections. Freeze the shared planning paths, accepted operations, and current `contract_sha256` / `plan_sha256` as this invocation's approved context; verify it using Step 2b before implementation. Revision repeats planning validation; cancellation stops without saving or mutation. Already-approved scoped child calls and valid creation fast-path calls do not repeat this gate. ### Step 3 — Setup Dataverse Web API auth Required only after implementation approval. For approved existing-table bindings with no schema mutation, skip to Step 6, not the schema-write phases. #### Step 3a — Environment consistency check The Power Apps CLI (`$PA`) and `az` authenticate independently — they can point to different accounts. Verify `power.config.json` resolves and `az` can token for the target tenant before making any Dataverse API calls: ```bash cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; } ENVIRONMENT_ID=$(node -p "require('./power.config.json').environmentId") || exit 1 ENV_JSON=$(node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$ENVIRONMENT_ID") || exit 1 echo "$ENV_JSON" az account show --query "{user: user.name, tenant: tenantId}" -o json ``` Compare the resolved environment URL with `<envUrl>` captured in Step 1. If they differ, **STOP** and warn: > "⚠️ Environment mismatch detected: > - resolver reports: `<resolved_env_url>` > - This project targets: `<envUrl>` > > The Dataverse API token comes from `az`, which must target the same tenant as the selected environment. Run: > ```bash > cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; } > az login --tenant <tenant-id> # switch az to the right tenant > ``` > Then re-run `/add-dataverse`." **Do NOT proceed with table creation if environments don't match** — you'll create tables in the wrong org. #### Step 3b — Acquire token ```bash cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; } az account show --query "user.name" -o tsv ``` If empty, instruct `az login` and stop. **Script invocation contract — read this once, all subsequent calls in this skill follow it:** ```bash cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; } node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> <METHOD> <apiPath> \ [--body '<json>'] [--include-headers] \ --tenant-id '<tenantId-from-resolve-environment>' ``` - Three positional args, in order: `<envUrl>`, `<METHOD>` (GET / POST / PATCH / DELETE), `<apiPath>` (everything after `/api/data/v9.2/`).
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub