← Microsoft DataverseCONTENT HISTORY

Update to Microsoft Dataverse

Snapshot Oct 24, 2026 · 13:01 UTC · version 1.16.0

Collection source: downloaded plugin package. These snapshots do not have a confirmed matching collection source. Differences in file lists alone do not establish changes to the package.

WHAT CHANGED

Instructions updated for dv-security

Skill instructions — Now says: --- name: dv-security description: Security-role assignment, user access, application users, business units, and admin self-elevation in Dataverse...

Observed in instructions or declared skills. Runtime behavior has not been tested.

Save Microsoft Dataverse and check future changes in Following.

Up to 3 plugins free · no card required.

All fields and original values.

Skill instructions

Before

Sep 30, 2026 · 23:13 UTC

--- name: dv-security description: Security-role assignment, user access, application users, business units, and admin self-elevation in Dataverse environments. Use when the user wants to give someone access, grant a role, become an ad...

After

Oct 24, 2026 · 13:01 UTC

--- name: dv-security description: Security-role assignment, user access, application users, business units, and admin self-elevation in Dataverse environments. Use when the user wants to give someone access, grant a role, become an admi...

Compare saved observations

Download comparison JSON

SKILL.md text changes

− removed · + added

--- before
+++ after
@@ -1,149 +1,149 @@
----
-name: dv-security
-description: Security-role assignment, user access, application users, business units, and admin self-elevation in Dataverse environments. Use when the user wants to give someone access, grant a role, become an admin, or add a service principal.
----
-
-# Skill: Security — Role Assignment and Self-Elevation
-
-**This skill uses first-party CLIs — PAC CLI for role changes, Dataverse CLI to verify.** Do NOT write Python scripts for role operations.
-
-## Preview Before Running
-
-Role grants and self-elevate are destructive (they change security posture and are logged to Purview). Before running, preview the action in plain prose — target user, role, environment(s) — using placeholders (`<ENV_URL>`, `<USER_EMAIL>`) for anything unknown, and ask for confirmation and missing values in the same turn. Skip the raw `pac admin` block; the user shouldn't have to read CLI syntax to approve a security change.
-
-**Key principle:** the user should be able to evaluate what's about to happen from your first response. A bare *"which environment?"* fails that test; a one-line prose preview passes it.
-
-### Examples
-
-**Assign role (user given, env missing):**
-- ❌ "Which environment should I target?"
-- ✅ "I'll assign **System Administrator** to `user@contoso.com` on `<ENV_URL>`. Confirm to proceed and provide the target environment URL (or 'all' to list and batch)."
-
-**Admin access across all environments:**
-- ❌ "Please provide your email address."
-- ✅ "I'll list your environments, then assign **System Administrator** in parallel on each one for `<YOUR_UPN>`. If `assign-user` fails on any environment, I'll fall back to self-elevate (logged to Purview) for that one. Confirm to proceed and provide your UPN."
-
-## Skill boundaries
-
-| Need | Use instead |
-|---|---|
-| Create or modify tables, columns, relationships | **dv-metadata** |
-| Manage org settings, audit, bulk delete, retention | **dv-admin** |
-| Query or read records | **dv-query** |
-| Write, update, or delete records | **dv-data** |
-| Tenant-level governance (DLP, env lifecycle) | `pac admin --help` |
-
-## Prerequisites
-
-- PAC CLI installed and authenticated (`pac auth create`)
-- System Administrator role in target environment (or Global/PP/D365 Admin for self-elevate)
-- Active auth profile: `pac auth list`
-- **Headless / restricted-egress hosts**: SDK handles role / user / business-unit ops; service principal for PAC-only ops; verify egress with `python scripts/auth.py --check`. See `dv-connect/references/headless-hosts.md`.
-
----
-
-## Assign a Security Role to a User
-
-```bash
-pac admin assign-user --user <email-or-object-id> --role "System Administrator" --environment <url>
-```
-
-### Arguments
-
-| Argument | Alias | Required | Description |
-|----------|-------|----------|-------------|
-| `--user` | `-u` | Yes | User email (UPN) or Azure AD object ID |
-| `--role` | `-r` | Yes | Security role name (e.g., `System Administrator`, `Basic User`) |
-| `--environment` | `-env` | Yes | Target environment URL or ID |
-| `--application-user` | `-au` | No | Treat user as an application user (service principal) |
-| `--business-unit` | `-bu` | No | Business unit ID. Defaults to the caller's business unit |
-
----
-
-## Verify the assignment — exit code 0 is not proof
-
-`pac admin assign-user` **exits 0 even when it fails** (unresolved environment, wrong role name, unknown user). Never treat a clean exit as success.
-
-1. **Read the output, not just the exit code.** A failed run still exits 0 but prints an error (`environment ... not found`, `role ... does not exist`). Stop if the output contains an error.
-2. **Confirm against the exact `--environment` you used** — do not re-resolve or shorten it; a different id silently "succeeds" on the wrong org. Query the user's roles with a Dataverse CLI read:
-
-```bash
-# Resolve the user's systemuserid, then list their assigned roles.
-# --context carries plugin/skill/agent attribution on the managed CLI call.
-dataverse api request --target dataverse --method GET \
-  --path "/api/data/v9.2/systemusers?%24select=systemuserid&%24filter=internalemailaddress eq 'user@contoso.com'" \
-  --environment <same-url-as-assign> \
-  --context "app=dataverse-skills/<ver>;skill=dv-security;agent=<agent>"
-dataverse api request --target dataverse --method GET \
-  --path "/api/data/v9.2/systemusers(<systemuserid>)/systemuserroles_association?%24select=name" \
-  --environment <same-url-as-assign> \
-  --context "app=dataverse-skills/<ver>;skill=dv-security;agent=<agent>"
-```
-
-If the first query returns no row, the sign-in identity may live on `domainname` (the AAD UPN) rather than `internalemailaddress` (Primary Email) — retry with `%24filter=domainname eq '<upn>'`, or `azureactivedirectoryobjectid eq '<objectid>'` when you assigned by object id. A missing row is not proof the grant failed.
-
-If the target role is absent, the assignment did not take — re-run, read the output, or fall back to self-elevate.
-
----
-
-## Batch Workflow: Assign Role Across Multiple Environments
-
-Run in parallel — never sequentially:
-
-```
-Step 1: pac admin list                                              -> Get all environments
-Step 2: Filter by type if needed (e.g., Developer, Sandbox)        -> Identify targets
-Step 3: Confirm with user — show list of target environments
-Step 4: Run ALL assignments in a single bash call:
-```
-
-```bash
-pac admin assign-user --user user@contoso.com --role "System Administrator" --environment https://dev1.crm.dynamics.com &
-pac admin assign-user --user user@contoso.com --role "System Administrator" --environment https://dev2.crm.dynamics.com &
-pac admin assign-user --user user@contoso.com --role "System Administrator" --environment https://dev3.crm.dynamics.com &
-wait
-```
-
-```
-Step 5: Verify each landed (exit 0 is not proof — see above), then report ("Assigned + verified on 3/3 environments")
-```
-
-**Important**: Always confirm which environments will be affected before assigning roles, and verify each assignment landed — a clean exit code does not prove success.
-
----
-
-## Tenant Admin Self-Elevation (Fallback)
-
-**Self-elevation is materially different from assigning a role to another user.** `pac admin assign-user <other>` grants privilege *to someone else*; `pac admin self-elevate` grants privilege *to the caller*. The risk profile and audit posture are different, so the confirmation protocol is stricter.
-
-If `pac admin assign-user` fails with "user has not been assigned any roles", use:
-
-```bash
-pac admin self-elevate --environment https://myorg.crm.dynamics.com
-```
-
-- Requires Global Admin, Power Platform Admin, or Dynamics 365 Admin
-- All elevations are logged to Microsoft Purview
-- Uses the active auth profile if `--environment` is omitted
-
-### Self-elevation confirmation protocol (stricter than assign-user)
-
-Before running `pac admin self-elevate`, the agent MUST:
-
-1. **State the risk explicitly.** Include this wording (or equivalent) in the pre-run summary:
-   > "This grants YOU System Administrator on `<env>`. The action is logged to Microsoft Purview with your identity and timestamp."
-2. **Capture a reason.** Ask for a one-line reason — ticket ID, incident number, or a free-form note such as `"dev sandbox access — no ticket"`. Echo the reason back in the pre-run summary so the user sees what will be on the record.
-3. **Wait for an explicit confirmation AFTER the user has seen both (1) and (2).** Do NOT accept a bare "yes" given before the risk statement and reason are on screen.
-4. **Do NOT silently fall back.** If `pac admin assign-user` fails, surface the failure first, then offer `self-elevate` with this protocol — never chain them automatically.
-
-**Flow**: Always try `pac admin assign-user` first. `admin self-elevate` is the documented fallback, gated by the protocol above.
-
-**CLI fallback**: If `pac admin self-elevate` errors out, self-elevate manually via **Power Platform Admin Center** → select the environment → **Access** → **System Administrator role**. All elevations are still logged to Purview. (In PAC CLI 2.6.4 the command fails with `bolt.authentication.http.AuthenticatedClientException` / `ApiVersionInvalid` because the CLI sends an empty `api-version=` to the backend.)
-
----
-
-## Safety Rules
-
-- **Always confirm** before assigning System Administrator role
-- Show the list of target environments before batch operations
-- Self-elevation is logged and auditable — warn the user
+---
+name: dv-security
+description: Security-role assignment, user access, application users, business units, and admin self-elevation in Dataverse environments. Use when the user wants to give someone access, grant a role, become an admin, or add a service principal.
+---
+
+# Skill: Security — Role Assignment and Self-Elevation
+
+**This skill uses first-party CLIs — PAC CLI for role changes, Dataverse CLI to verify.** Do NOT write Python scripts for role operations.
+
+## Preview Before Running
+
+Role grants and self-elevate are destructive (they change security posture and are logged to Purview). Before running, preview the action in plain prose — target user, role, environment(s) — using placeholders (`<ENV_URL>`, `<USER_EMAIL>`) for anything unknown, and ask for confirmation and missing values in the same turn. Skip the raw `pac admin` block; the user shouldn't have to read CLI syntax to approve a security change.
+
+**Key principle:** the user should be able to evaluate what's about to happen from your first response. A bare *"which environment?"* fails that test; a one-line prose preview passes it.
+
+### Examples
+
+**Assign role (user given, env missing):**
+- ❌ "Which environment should I target?"
+- ✅ "I'll assign **System Administrator** to `user@contoso.com` on `<ENV_URL>`. Confirm to proceed and provide the target environment URL (or 'all' to list and batch)."
+
+**Admin access across all environments:**
+- ❌ "Please provide your email address."
+- ✅ "I'll list your environments, then assign **System Administrator** in parallel on each one for `<YOUR_UPN>`. If `assign-user` fails on any environment, I'll fall back to self-elevate (logged to Purview) for that one. Confirm to proceed and provide your UPN."
+
+## Skill boundaries
+
+| Need | Use instead |
+|---|---|
+| Create or modify tables, columns, relationships | **dv-metadata** |
+| Manage org settings, audit, bulk delete, retention | **dv-admin** |
+| Query or read records | **dv-query** |
+| Write, update, or delete records | **dv-data** |
+| Tenant-level governance (DLP, env lifecycle) | `pac admin --help` |
+
+## Prerequisites
+
+- PAC CLI installed and authenticated (`pac auth create`)
+- System Administrator role in target environment (or Global/PP/D365 Admin for self-elevate)
+- Active auth profile: `pac auth list`
+- **Headless / restricted-egress hosts**: SDK handles role / user / business-unit ops; service principal for PAC-only ops; verify egress with `python scripts/auth.py --check`. See `dv-connect/references/headless-hosts.md`.
+
+---
+
+## Assign a Security Role to a User
+
+```bash
+pac admin assign-user --user <email-or-object-id> --role "System Administrator" --environment <url>
+```
+
+### Arguments
+
+| Argument | Alias | Required | Description |
+|----------|-------|----------|-------------|
+| `--user` | `-u` | Yes | User email (UPN) or Azure AD object ID |
+| `--role` | `-r` | Yes | Security role name (e.g., `System Administrator`, `Basic User`) |
+| `--environment` | `-env` | Yes | Target environment URL or ID |
+| `--application-user` | `-au` | No | Treat user as an application user (service principal) |
+| `--business-unit` | `-bu` | No | Business unit ID. Defaults to the caller's business unit |
+
+---
+
+## Verify the assignment — exit code 0 is not proof
+
+`pac admin assign-user` **exits 0 even when it fails** (unresolved environment, wrong role name, unknown user). Never treat a clean exit as success.
+
+1. **Read the output, not just the exit code.** A failed run still exits 0 but prints an error (`environment ... not found`, `role ... does not exist`). Stop if the output contains an error.
+2. **Confirm against the exact `--environment` you used** — do not re-resolve or shorten it; a different id silently "succeeds" on the wrong org. Query the user's roles with a Dataverse CLI read:
+
+```bash
+# Resolve the user's systemuserid, then list their assigned roles.
+# --context carries plugin/skill/agent attribution on the managed CLI call.
+dataverse api request --target dataverse --method GET \
+  --path "/api/data/v9.2/systemusers?%24select=systemuserid&%24filter=internalemailaddress eq 'user@contoso.com'" \
+  --environment <same-url-as-assign> \
+  --context "app=dataverse-skills/<ver>;skill=dv-security;agent=<agent>"
+dataverse api request --target dataverse --method GET \
+  --path "/api/data/v9.2/systemusers(<systemuserid>)/systemuserroles_association?%24select=name" \
+  --environment <same-url-as-assign> \
+  --context "app=dataverse-skills/<ver>;skill=dv-security;agent=<agent>"
+```
+
+If the first query returns no row, the sign-in identity may live on `domainname` (the AAD UPN) rather than `internalemailaddress` (Primary Email) — retry with `%24filter=domainname eq '<upn>'`, or `azureactivedirectoryobjectid eq '<objectid>'` when you assigned by object id. A missing row is not proof the grant failed.
+
+If the target role is absent, the assignment did not take — re-run, read the output, or fall back to self-elevate.
+
+---
+
+## Batch Workflow: Assign Role Across Multiple Environments
+
+Run in parallel — never sequentially:
+
+```
+Step 1: pac admin list                                              -> Get all environments
+Step 2: Filter by type if needed (e.g., Developer, Sandbox)        -> Identify targets
+Step 3: Confirm with user — show list of target environments
+Step 4: Run ALL assignments in a single bash call:
+```
+
+```bash
+pac admin assign-user --user user@contoso.com --role "System Administrator" --environment https://dev1.crm.dynamics.com &
+pac admin assign-user --user user@contoso.com --role "System Administrator" --environment https://dev2.crm.dynamics.com &
+pac admin assign-user --user user@contoso.com --role "System Administrator" --environment https://dev3.crm.dynamics.com &
+wait
+```
+
+```
+Step 5: Verify each landed (exit 0 is not proof — see above), then report ("Assigned + verified on 3/3 environments")
+```
+
+**Important**: Always confirm which environments will be affected before assigning roles, and verify each assignment landed — a clean exit code does not prove success.
+
+---
+
+## Tenant Admin Self-Elevation (Fallback)
+
+**Self-elevation is materially different from assigning a role to another user.** `pac admin assign-user <other>` grants privilege *to someone else*; `pac admin self-elevate` grants privilege *to the caller*. The risk profile and audit posture are different, so the confirmation protocol is stricter.
+
+If `pac admin assign-user` fails with "user has not been assigned any roles", use:
+
+```bash
+pac admin self-elevate --environment https://myorg.crm.dynamics.com
+```
+
+- Requires Global Admin, Power Platform Admin, or Dynamics 365 Admin
+- All elevations are logged to Microsoft Purview
+- Uses the active auth profile if `--environment` is omitted
+
+### Self-elevation confirmation protocol (stricter than assign-user)
+
+Before running `pac admin self-elevate`, the agent MUST:
+
+1. **State the risk explicitly.** Include this wording (or equivalent) in the pre-run summary:
+   > "This grants YOU System Administrator on `<env>`. The action is logged to Microsoft Purview with your identity and timestamp."
+2. **Capture a reason.** Ask for a one-line reason — ticket ID, incident number, or a free-form note such as `"dev sandbox access — no ticket"`. Echo the reason back in the pre-run summary so the user sees what will be on the record.
+3. **Wait for an explicit confirmation AFTER the user has seen both (1) and (2).** Do NOT accept a bare "yes" given before the risk statement and reason are on screen.
+4. **Do NOT silently fall back.** If `pac admin assign-user` fails, surface the failure first, then offer `self-elevate` with this protocol — never chain them automatically.
+
+**Flow**: Always try `pac admin assign-user` first. `admin self-elevate` is the documented fallback, gated by the protocol above.
+
+**CLI fallback**: If `pac admin self-elevate` errors out, self-elevate manually via **Power Platform Admin Center** → select the environment → **Access** → **System Administrator role**. All elevations are still logged to Purview. (In PAC CLI 2.6.4 the command fails with `bolt.authentication.http.AuthenticatedClientException` / `ApiVersionInvalid` because the CLI sends an empty `api-version=` to the backend.)
+
+---
+
+## Safety Rules
+
+- **Always confirm** before assigning System Administrator role
+- Show the list of target environments before batch operations
+- Self-elevation is logged and auditable — warn the user
Full technical diff · 1 changed fields

changed /skill_md_contents

BEFORE
"---\r\nname: dv-security\r\ndescription: Security-role assignment, user access, application users, business units, and admin self-elevation in Dataverse environments. Use when the user wants to give someone access, grant a role, become an admin, or add a service principal.\r\n---\r\n\r\n# Skill: Security — Role Assignment and Self-Elevation\r\n\r\n**This skill uses first-party CLIs — PAC CLI for role changes, Dataverse CLI to verify.** Do NOT write Python scripts for role operations.\r\n\r\n## Preview Before Running\r\n\r\nRole grants and self-elevate are destructive (they change security posture and are logged to Purview). Before running, preview the action in plain prose — target user, role, environment(s) — using placeholders (`<ENV_URL>`, `<USER_EMAIL>`) for anything unknown, and ask for confirmation and missing values in the same turn. Skip the raw `pac admin` block; the user shouldn't have to read CLI syntax to approve a security change.\r\n\r\n**Key principle:** the user should be able to evaluate what's about to happen from your first response. A bare *\"which environment?\"* fails that test; a one-line prose preview passes it.\r\n\r\n### Examples\r\n\r\n**Assign role (user given, env missing):**\r\n- ❌ \"Which environment should I target?\"\r\n- ✅ \"I'll assign **System Administrator** to `user@contoso.com` on `<ENV_URL>`. Confirm to proceed and provide the target environment URL (or 'all' to list and batch).\"\r\n\r\n**Admin access across all environments:**\r\n- ❌ \"Please provide your email address.\"\r\n- ✅ \"I'll list your environments, then assign **System Administrator** in parallel on each one for `<YOUR_UPN>`. If `assign-user` fails on any environment, I'll fall back to self-elevate (logged to Purview) for that one. Confirm to proceed and provide your UPN.\"\r\n\r\n## Skill boundaries\r\n\r\n| Need | Use instead |\r\n|---|---|\r\n| Create or modify tables, columns, relationships | **dv-metadata** |\r\n| Manage org settings, audit, bulk delete, retention | **dv-admin** |\r\n| Query or read records | **dv-query** |\r\n| Write, update, or delete records | **dv-data** |\r\n| Tenant-level governance (DLP, env lifecycle) | `pac admin --help` |\r\n\r\n## Prerequisites\r\n\r\n- PAC CLI installed and authenticated (`pac auth create`)\r\n- System Administrator role in target environment (or Global/PP/D365 Admin for self-elevate)\r\n- Active auth profile: `pac auth list`\r\n- **Headless / restricted-egress hosts**: SDK handles role / user / business-unit ops; service principal for PAC-only ops; verify egress with `python scripts/auth.py --check`. See `dv-connect/references/headless-hosts.md`.\r\n\r\n---\r\n\r\n## Assign a Security Role to a User\r\n\r\n```bash\r\npac admin assign-user --user <email-or-object-id> --role \"System Administrator\" --environment <url>\r\n```\r\n\r\n### Arguments\r\n\r\n| Argument | Alias | Required | Description |\r\n|----------|-------|----------|-------------|\r\n| `--user` | `-u` | Yes | User email (UPN) or Azure AD object ID |\r\n| `--role` | `-r` | Yes | Security role name (e.g., `System Administrator`, `Basic User`) |\r\n| `--environment` | `-env` | Yes | Target environment URL or ID |\r\n| `--application-user` | `-au` | No | Treat user as an application user (service principal) |\r\n| `--business-unit` | `-bu` | No | Business unit ID. Defaults to the caller's business unit |\r\n\r\n---\r\n\r\n## Verify the assignment — exit code 0 is not proof\r\n\r\n`pac admin assign-user` **exits 0 even when it fails** (unresolved environment, wrong role name, unknown user). Never treat a clean exit as success.\r\n\r\n1. **Read the output, not just the exit code.** A failed run still exits 0 but prints an error (`environment ... not found`, `role ... does not exist`). Stop if the output contains an error.\r\n2. **Confirm against the exact `--environment` you used** — do not re-resolve or shorten it; a different id silently \"succeeds\" on the wrong org. Query the user's roles with a Dataverse CLI read:\r\n\r\n```bash\r\n# Resolve the user's systemuserid, then list their assigned roles.\r\n# --context carries plugin/skill/agent attribution on the managed CLI call.\r\ndataverse api request --target dataverse --method GET \\\r\n  --path \"/api/data/v9.2/systemusers?%24select=systemuserid&%24filter=internalemailaddress eq 'user@contoso.com'\" \\\r\n  --environment <same-url-as-assign> \\\r\n  --context \"app=dataverse-skills/<ver>;skill=dv-security;agent=<agent>\"\r\ndataverse api request --target dataverse --method GET \\\r\n  --path \"/api/data/v9.2/systemusers(<systemuserid>)/systemuserroles_association?%24select=name\" \\\r\n  --environment <same-url-as-assign> \\\r\n  --context \"app=dataverse-skills/<ver>;skill=dv-security;agent=<agent>\"\r\n```\r\n\r\nIf the first query returns no row, the sign-in identity may live on `domainname` (the AAD UPN) rather than `internalemailaddress` (Primary Email) — retry with `%24filter=domainname eq '<upn>'`, or `azureactivedirectoryobjectid eq '<objectid>'` when you assigned by object id. A missing row is not proof the grant failed.\r\n\r\nIf the target role is absent, the assignment did not take — re-run, read the output, or fall back to self-elevate.\r\n\r\n---\r\n\r\n## Batch Workflow: Assign Role Across Multiple Environments\r\n\r\nRun in parallel — never sequentially:\r\n\r\n```\r\nStep 1: pac admin list                                              -> Get all environments\r\nStep 2: Filter by type if needed (e.g., Developer, Sandbox)        -> Identify targets\r\nStep 3: Confirm with user — show list of target environments\r\nStep 4: Run ALL assignments in a single bash call:\r\n```\r\n\r\n```bash\r\npac admin assign-user --user user@contoso.com --role \"System Administrator\" --environment https://dev1.crm.dynamics.com &\r\npac admin assign-user --user user@contoso.com --role \"System Administrator\" --environment https://dev2.crm.dynamics.com &\r\npac admin assign-user --user user@contoso.com --role \"System Administrator\" --environment https://dev3.crm.dynamics.com &\r\nwait\r\n```\r\n\r\n```\r\nStep 5: Verify each landed (exit 0 is not proof — see above), then report (\"Assigned + verified on 3/3 environments\")\r\n```\r\n\r\n**Important**: Always confirm which environments will be affected before assigning roles, and verify each assignment landed — a clean exit code does not prove success.\r\n\r\n---\r\n\r\n## Tenant Admin Self-Elevation (Fallback)\r\n\r\n**Self-elevation is materially different from assigning a role to another user.** `pac admin assign-user <other>` grants privilege *to someone else*; `pac admin self-elevate` grants privilege *to the caller*. The risk profile and audit posture are different, so the confirmation protocol is stricter.\r\n\r\nIf `pac admin assign-user` fails with \"user has not been assigned any roles\", use:\r\n\r\n```bash\r\npac admin self-elevate --environment https://myorg.crm.dynamics.com\r\n```\r\n\r\n- Requires Global Admin, Power Platform Admin, or Dynamics 365 Admin\r\n- All elevations are logged to Microsoft Purview\r\n- Uses the active auth profile if `--environment` is omitted\r\n\r\n### Self-elevation confirmation protocol (stricter than assign-user)\r\n\r\nBefore running `pac admin self-elevate`, the agent MUST:\r\n\r\n1. **State the risk explicitly.** Include this wording (or equivalent) in the pre-run summary:\r\n   > \"This grants YOU System Administrator on `<env>`. The action is logged to Microsoft Purview with your identity and timestamp.\"\r\n2. **Capture a reason.** Ask for a one-line reason — ticket ID, incident number, or a free-form note such as `\"dev sandbox access — no ticket\"`. Echo the reason back in the pre-run summary so the user sees what will be on the record.\r\n3. **Wait for an explicit confirmation AFTER the user has seen both (1) and (2).** Do NOT accept a bare \"yes\" given before the risk statement and reason are on screen.\r\n4. **Do NOT silently fall back.** If `pac admin assign-user` fails, surface the failure first, then offer `self-elevate` with this protocol — never chain them automatically.\r\n\r\n**Flow**: Always try `pac admin assign-user` first. `admin self-elevate` is the documented fallback, gated by the protocol above.\r\n\r\n**CLI fallback**: If `pac admin self-elevate` errors out, self-elevate manually via **Power Platform Admin Center** → select the environment → **Access** → **System Administrator role**. All elevations are still logged to Purview. (In PAC CLI 2.6.4 the command fails with `bolt.authentication.http.AuthenticatedClientException` / `ApiVersionInvalid` because the CLI sends an empty `api-version=` to the backend.)\r\n\r\n---\r\n\r\n## Safety Rules\r\n\r\n- **Always confirm** before assigning System Administrator role\r\n- Show the list of target environments before batch operations\r\n- Self-elevation is logged and auditable — warn the user\r\n"
AFTER
"---\nname: dv-security\ndescription: Security-role assignment, user access, application users, business units, and admin self-elevation in Dataverse environments. Use when the user wants to give someone access, grant a role, become an admin, or add a service principal.\n---\n\n# Skill: Security — Role Assignment and Self-Elevation\n\n**This skill uses first-party CLIs — PAC CLI for role changes, Dataverse CLI to verify.** Do NOT write Python scripts for role operations.\n\n## Preview Before Running\n\nRole grants and self-elevate are destructive (they change security posture and are logged to Purview). Before running, preview the action in plain prose — target user, role, environment(s) — using placeholders (`<ENV_URL>`, `<USER_EMAIL>`) for anything unknown, and ask for confirmation and missing values in the same turn. Skip the raw `pac admin` block; the user shouldn't have to read CLI syntax to approve a security change.\n\n**Key principle:** the user should be able to evaluate what's about to happen from your first response. A bare *\"which environment?\"* fails that test; a one-line prose preview passes it.\n\n### Examples\n\n**Assign role (user given, env missing):**\n- ❌ \"Which environment should I target?\"\n- ✅ \"I'll assign **System Administrator** to `user@contoso.com` on `<ENV_URL>`. Confirm to proceed and provide the target environment URL (or 'all' to list and batch).\"\n\n**Admin access across all environments:**\n- ❌ \"Please provide your email address.\"\n- ✅ \"I'll list your environments, then assign **System Administrator** in parallel on each one for `<YOUR_UPN>`. If `assign-user` fails on any environment, I'll fall back to self-elevate (logged to Purview) for that one. Confirm to proceed and provide your UPN.\"\n\n## Skill boundaries\n\n| Need | Use instead |\n|---|---|\n| Create or modify tables, columns, relationships | **dv-metadata** |\n| Manage org settings, audit, bulk delete, retention | **dv-admin** |\n| Query or read records | **dv-query** |\n| Write, update, or delete records | **dv-data** |\n| Tenant-level governance (DLP, env lifecycle) | `pac admin --help` |\n\n## Prerequisites\n\n- PAC CLI installed and authenticated (`pac auth create`)\n- System Administrator role in target environment (or Global/PP/D365 Admin for self-elevate)\n- Active auth profile: `pac auth list`\n- **Headless / restricted-egress hosts**: SDK handles role / user / business-unit ops; service principal for PAC-only ops; verify egress with `python scripts/auth.py --check`. See `dv-connect/references/headless-hosts.md`.\n\n---\n\n## Assign a Security Role to a User\n\n```bash\npac admin assign-user --user <email-or-object-id> --role \"System Administrator\" --environment <url>\n```\n\n### Arguments\n\n| Argument | Alias | Required | Description |\n|----------|-------|----------|-------------|\n| `--user` | `-u` | Yes | User email (UPN) or Azure AD object ID |\n| `--role` | `-r` | Yes | Security role name (e.g., `System Administrator`, `Basic User`) |\n| `--environment` | `-env` | Yes | Target environment URL or ID |\n| `--application-user` | `-au` | No | Treat user as an application user (service principal) |\n| `--business-unit` | `-bu` | No | Business unit ID. Defaults to the caller's business unit |\n\n---\n\n## Verify the assignment — exit code 0 is not proof\n\n`pac admin assign-user` **exits 0 even when it fails** (unresolved environment, wrong role name, unknown user). Never treat a clean exit as success.\n\n1. **Read the output, not just the exit code.** A failed run still exits 0 but prints an error (`environment ... not found`, `role ... does not exist`). Stop if the output contains an error.\n2. **Confirm against the exact `--environment` you used** — do not re-resolve or shorten it; a different id silently \"succeeds\" on the wrong org. Query the user's roles with a Dataverse CLI read:\n\n```bash\n# Resolve the user's systemuserid, then list their assigned roles.\n# --context carries plugin/skill/agent attribution on the managed CLI call.\ndataverse api request --target dataverse --method GET \\\n  --path \"/api/data/v9.2/systemusers?%24select=systemuserid&%24filter=internalemailaddress eq 'user@contoso.com'\" \\\n  --environment <same-url-as-assign> \\\n  --context \"app=dataverse-skills/<ver>;skill=dv-security;agent=<agent>\"\ndataverse api request --target dataverse --method GET \\\n  --path \"/api/data/v9.2/systemusers(<systemuserid>)/systemuserroles_association?%24select=name\" \\\n  --environment <same-url-as-assign> \\\n  --context \"app=dataverse-skills/<ver>;skill=dv-security;agent=<agent>\"\n```\n\nIf the first query returns no row, the sign-in identity may live on `domainname` (the AAD UPN) rather than `internalemailaddress` (Primary Email) — retry with `%24filter=domainname eq '<upn>'`, or `azureactivedirectoryobjectid eq '<objectid>'` when you assigned by object id. A missing row is not proof the grant failed.\n\nIf the target role is absent, the assignment did not take — re-run, read the output, or fall back to self-elevate.\n\n---\n\n## Batch Workflow: Assign Role Across Multiple Environments\n\nRun in parallel — never sequentially:\n\n```\nStep 1: pac admin list                                              -> Get all environments\nStep 2: Filter by type if needed (e.g., Developer, Sandbox)        -> Identify targets\nStep 3: Confirm with user — show list of target environments\nStep 4: Run ALL assignments in a single bash call:\n```\n\n```bash\npac admin assign-user --user user@contoso.com --role \"System Administrator\" --environment https://dev1.crm.dynamics.com &\npac admin assign-user --user user@contoso.com --role \"System Administrator\" --environment https://dev2.crm.dynamics.com &\npac admin assign-user --user user@contoso.com --role \"System Administrator\" --environment https://dev3.crm.dynamics.com &\nwait\n```\n\n```\nStep 5: Verify each landed (exit 0 is not proof — see above), then report (\"Assigned + verified on 3/3 environments\")\n```\n\n**Important**: Always confirm which environments will be affected before assigning roles, and verify each assignment landed — a clean exit code does not prove success.\n\n---\n\n## Tenant Admin Self-Elevation (Fallback)\n\n**Self-elevation is materially different from assigning a role to another user.** `pac admin assign-user <other>` grants privilege *to someone else*; `pac admin self-elevate` grants privilege *to the caller*. The risk profile and audit posture are different, so the confirmation protocol is stricter.\n\nIf `pac admin assign-user` fails with \"user has not been assigned any roles\", use:\n\n```bash\npac admin self-elevate --environment https://myorg.crm.dynamics.com\n```\n\n- Requires Global Admin, Power Platform Admin, or Dynamics 365 Admin\n- All elevations are logged to Microsoft Purview\n- Uses the active auth profile if `--environment` is omitted\n\n### Self-elevation confirmation protocol (stricter than assign-user)\n\nBefore running `pac admin self-elevate`, the agent MUST:\n\n1. **State the risk explicitly.** Include this wording (or equivalent) in the pre-run summary:\n   > \"This grants YOU System Administrator on `<env>`. The action is logged to Microsoft Purview with your identity and timestamp.\"\n2. **Capture a reason.** Ask for a one-line reason — ticket ID, incident number, or a free-form note such as `\"dev sandbox access — no ticket\"`. Echo the reason back in the pre-run summary so the user sees what will be on the record.\n3. **Wait for an explicit confirmation AFTER the user has seen both (1) and (2).** Do NOT accept a bare \"yes\" given before the risk statement and reason are on screen.\n4. **Do NOT silently fall back.** If `pac admin assign-user` fails, surface the failure first, then offer `self-elevate` with this protocol — never chain them automatically.\n\n**Flow**: Always try `pac admin assign-user` first. `admin self-elevate` is the documented fallback, gated by the protocol above.\n\n**CLI fallback**: If `pac admin self-elevate` errors out, self-elevate manually via **Power Platform Admin Center** → select the environment → **Access** → **System Administrator role**. All elevations are still logged to Purview. (In PAC CLI 2.6.4 the command fails with `bolt.authentication.http.AuthenticatedClientException` / `ApiVersionInvalid` because the CLI sends an empty `api-version=` to the backend.)\n\n---\n\n## Safety Rules\n\n- **Always confirm** before assigning System Administrator role\n- Show the list of target environments before batch operations\n- Self-elevation is logged and auditable — warn the user\n"
Full snapshot data
{
  "description": "Security-role assignment, user access, application users, business units, and admin self-elevation in Dataverse environments. Use when the user wants to give someone access, grant a role, become an admin, or add a service principal.",
  "included_files": [],
  "name": "dv-security",
  "skill_md_contents": "---\nname: dv-security\ndescription: Security-role assignment, user access, application users, business units, and admin self-elevation in Dataverse environments. Use when the user wants to give someone access, grant a role, become an admin, or add a service principal.\n---\n\n# Skill: Security — Role Assignment and Self-Elevation\n\n**This skill uses first-party CLIs — PAC CLI for role changes, Dataverse CLI to verify.** Do NOT write Python scripts for role operations.\n\n## Preview Before Running\n\nRole grants and self-elevate are destructive (they change security posture and are logged to Purview). Before running, preview the action in plain prose — target user, role, environment(s) — using placeholders (`<ENV_URL>`, `<USER_EMAIL>`) for anything unknown, and ask for confirmation and missing values in the same turn. Skip the raw `pac admin` block; the user shouldn't have to read CLI syntax to approve a security change.\n\n**Key principle:** the user should be able to evaluate what's about to happen from your first response. A bare *\"which environment?\"* fails that test; a one-line prose preview passes it.\n\n### Examples\n\n**Assign role (user given, env missing):**\n- ❌ \"Which environment should I target?\"\n- ✅ \"I'll assign **System Administrator** to `user@contoso.com` on `<ENV_URL>`. Confirm to proceed and provide the target environment URL (or 'all' to list and batch).\"\n\n**Admin access across all environments:**\n- ❌ \"Please provide your email address.\"\n- ✅ \"I'll list your environments, then assign **System Administrator** in parallel on each one for `<YOUR_UPN>`. If `assign-user` fails on any environment, I'll fall back to self-elevate (logged to Purview) for that one. Confirm to proceed and provide your UPN.\"\n\n## Skill boundaries\n\n| Need | Use instead |\n|---|---|\n| Create or modify tables, columns, relationships | **dv-metadata** |\n| Manage org settings, audit, bulk delete, retention | **dv-admin** |\n| Query or read records | **dv-query** |\n| Write, update, or delete records | **dv-data** |\n| Tenant-level governance (DLP, env lifecycle) | `pac admin --help` |\n\n## Prerequisites\n\n- PAC CLI installed and authenticated (`pac auth create`)\n- System Administrator role in target environment (or Global/PP/D365 Admin for self-elevate)\n- Active auth profile: `pac auth list`\n- **Headless / restricted-egress hosts**: SDK handles role / user / business-unit ops; service principal for PAC-only ops; verify egress with `python scripts/auth.py --check`. See `dv-connect/references/headless-hosts.md`.\n\n---\n\n## Assign a Security Role to a User\n\n```bash\npac admin assign-user --user <email-or-object-id> --role \"System Administrator\" --environment <url>\n```\n\n### Arguments\n\n| Argument | Alias | Required | Description |\n|----------|-------|----------|-------------|\n| `--user` | `-u` | Yes | User email (UPN) or Azure AD object ID |\n| `--role` | `-r` | Yes | Security role name (e.g., `System Administrator`, `Basic User`) |\n| `--environment` | `-env` | Yes | Target environment URL or ID |\n| `--application-user` | `-au` | No | Treat user as an application user (service principal) |\n| `--business-unit` | `-bu` | No | Business unit ID. Defaults to the caller's business unit |\n\n---\n\n## Verify the assignment — exit code 0 is not proof\n\n`pac admin assign-user` **exits 0 even when it fails** (unresolved environment, wrong role name, unknown user). Never treat a clean exit as success.\n\n1. **Read the output, not just the exit code.** A failed run still exits 0 but prints an error (`environment ... not found`, `role ... does not exist`). Stop if the output contains an error.\n2. **Confirm against the exact `--environment` you used** — do not re-resolve or shorten it; a different id silently \"succeeds\" on the wrong org. Query the user's roles with a Dataverse CLI read:\n\n```bash\n# Resolve the user's systemuserid, then list their assigned roles.\n# --context carries plugin/skill/agent attribution on the managed CLI call.\ndataverse api request --target dataverse --method GET \\\n  --path \"/api/data/v9.2/systemusers?%24select=systemuserid&%24filter=internalemailaddress eq 'user@contoso.com'\" \\\n  --environment <same-url-as-assign> \\\n  --context \"app=dataverse-skills/<ver>;skill=dv-security;agent=<agent>\"\ndataverse api request --target dataverse --method GET \\\n  --path \"/api/data/v9.2/systemusers(<systemuserid>)/systemuserroles_association?%24select=name\" \\\n  --environment <same-url-as-assign> \\\n  --context \"app=dataverse-skills/<ver>;skill=dv-security;agent=<agent>\"\n```\n\nIf the first query returns no row, the sign-in identity may live on `domainname` (the AAD UPN) rather than `internalemailaddress` (Primary Email) — retry with `%24filter=domainname eq '<upn>'`, or `azureactivedirectoryobjectid eq '<objectid>'` when you assigned by object id. A missing row is not proof the grant failed.\n\nIf the target role is absent, the assignment did not take — re-run, read the output, or fall back to self-elevate.\n\n---\n\n## Batch Workflow: Assign Role Across Multiple Environments\n\nRun in parallel — never sequentially:\n\n```\nStep 1: pac admin list                                              -> Get all environments\nStep 2: Filter by type if needed (e.g., Developer, Sandbox)        -> Identify targets\nStep 3: Confirm with user — show list of target environments\nStep 4: Run ALL assignments in a single bash call:\n```\n\n```bash\npac admin assign-user --user user@contoso.com --role \"System Administrator\" --environment https://dev1.crm.dynamics.com &\npac admin assign-user --user user@contoso.com --role \"System Administrator\" --environment https://dev2.crm.dynamics.com &\npac admin assign-user --user user@contoso.com --role \"System Administrator\" --environment https://dev3.crm.dynamics.com &\nwait\n```\n\n```\nStep 5: Verify each landed (exit 0 is not proof — see above), then report (\"Assigned + verified on 3/3 environments\")\n```\n\n**Important**: Always confirm which environments will be affected before assigning roles, and verify each assignment landed — a clean exit code does not prove success.\n\n---\n\n## Tenant Admin Self-Elevation (Fallback)\n\n**Self-elevation is materially different from assigning a role to another user.** `pac admin assign-user <other>` grants privilege *to someone else*; `pac admin self-elevate` grants privilege *to the caller*. The risk profile and audit posture are different, so the confirmation protocol is stricter.\n\nIf `pac admin assign-user` fails with \"user has not been assigned any roles\", use:\n\n```bash\npac admin self-elevate --environment https://myorg.crm.dynamics.com\n```\n\n- Requires Global Admin, Power Platform Admin, or Dynamics 365 Admin\n- All elevations are logged to Microsoft Purview\n- Uses the active auth profile if `--environment` is omitted\n\n### Self-elevation confirmation protocol (stricter than assign-user)\n\nBefore running `pac admin self-elevate`, the agent MUST:\n\n1. **State the risk explicitly.** Include this wording (or equivalent) in the pre-run summary:\n   > \"This grants YOU System Administrator on `<env>`. The action is logged to Microsoft Purview with your identity and timestamp.\"\n2. **Capture a reason.** Ask for a one-line reason — ticket ID, incident number, or a free-form note such as `\"dev sandbox access — no ticket\"`. Echo the reason back in the pre-run summary so the user sees what will be on the record.\n3. **Wait for an explicit confirmation AFTER the user has seen both (1) and (2).** Do NOT accept a bare \"yes\" given before the risk statement and reason are on screen.\n4. **Do NOT silently fall back.** If `pac admin assign-user` fails, surface the failure first, then offer `self-elevate` with this protocol — never chain them automatically.\n\n**Flow**: Always try `pac admin assign-user` first. `admin self-elevate` is the documented fallback, gated by the protocol above.\n\n**CLI fallback**: If `pac admin self-elevate` errors out, self-elevate manually via **Power Platform Admin Center** → select the environment → **Access** → **System Administrator role**. All elevations are still logged to Purview. (In PAC CLI 2.6.4 the command fails with `bolt.authentication.http.AuthenticatedClientException` / `ApiVersionInvalid` because the CLI sends an empty `api-version=` to the backend.)\n\n---\n\n## Safety Rules\n\n- **Always confirm** before assigning System Administrator role\n- Show the list of target environments before batch operations\n- Self-elevation is logged and auditable — warn the user\n"
}

SHA-256 of public snapshot: 9c82474f117de68402e2dd7917cd5c38a3e07f1f8a0c5be72a4807447bde937c