audit-permissions
This Claude Code skill audits table permissions on Power Pages code sites by analyzing permissions against site code and Dataverse metadata, then generates a visual HTML report with findings and recommended fixes. Use it to verify that table permissions align with actual site code usage and follow security best practices before deploying Power Pages applications.
git clone --depth 1 https://github.com/microsoft/power-platform-skills /tmp/audit-permissions && cp -r /tmp/audit-permissions/plugins/power-pages/skills/audit-permissions ~/.claude/skills/audit-permissionsSKILL.md
> **Plugin check**: Run `node "${CLAUDE_PLUGIN_ROOT}/scripts/check-version.js"` — if it outputs a message, show it to the user before proceeding.
# Audit Permissions
Audit existing table permissions on a Power Pages code site. Analyze permissions against the site code and Dataverse metadata, then generate a visual HTML audit report with findings, reasoning, and suggested fixes.
## Workflow
1. **Verify Site Deployment** — Check that `.powerpages-site` folder and table permissions exist
2. **Gather Configuration** — Read all web roles, table permissions, and site code
3. **Run Local Schema Validation** — Use the shared validator to detect invalid permission/site-setting YAML before deeper analysis
4. **Analyze & Discover** — Query Dataverse for relationships and lookup columns using deterministic scripts
5. **Run Audit Checks** — Compare permissions against code usage and best practices
6. **Generate Report** — Create the HTML audit report and display in browser
7. **Present Findings & Track** — Summarize findings, record skill usage, and ask user if they want to fix issues
**Important:** Do NOT ask the user questions during analysis. Autonomously gather all data, then present findings.
## Task Tracking
At the start of Step 1, create all tasks upfront using `TaskCreate`. Mark each task `in_progress` when starting and `completed` when done.
| Task subject | activeForm | Description |
|-------------|------------|-------------|
| Verify site deployment | Verifying site deployment | Check .powerpages-site folder and table permissions exist |
| Gather configuration | Gathering configuration | Read web roles, table permissions, and site code |
| Run local schema validation | Validating local permissions schema | Run shared validator against existing table permission and site setting YAML |
| Discover relationships | Discovering relationships | Query Dataverse for lookup columns and relationships |
| Run audit checks | Running audit checks | Create per-table tasks and run checklist (A–K) for each table, then cross-validate |
| Generate audit report | Generating audit report | Create HTML report and display in browser |
| Present findings | Presenting findings | Summarize results, record usage, and offer to fix issues |
**Note:** The "Run audit checks" phase creates **additional per-table tasks** dynamically in Step 4.2. These per-table tasks track the systematic A–K checklist for each table independently.
---
## Step 1: Verify Site Deployment
Use `Glob` to find:
- `**/powerpages.config.json` — identifies the project root
- `**/.powerpages-site/table-permissions/*.tablepermission.yml` — existing permissions
If no `.powerpages-site` folder exists, stop and tell the user to deploy first using `/deploy-site`.
If no table permissions exist, note this as a critical finding (the site may have no data access configured) and continue the audit — there may still be code references that need permissions.
---
## Step 2: Gather Configuration
### 2.1 Read Web Roles
Read all files matching `**/.powerpages-site/web-roles/*.yml`. Extract `id`, `name`, `anonymoususersrole`, `authenticatedusersrole` from each.
### 2.2 Read Table Permissions
Read all files matching `**/.powerpages-site/table-permissions/*.tablepermission.yml`. For each permission, extract:
- `entityname` (permission name)
- `entitylogicalname` (table)
- `scope` (numeric code)
- `read`, `create`, `write`, `delete`, `append`, `appendto` (boolean flags)
- `adx_entitypermission_webrole` (array of web role UUIDs)
- `contactrelationship`, `accountrelationship` (if Contact/Account scope)
- `parententitypermission`, `parentrelationship` (if parent scope)
### 2.3 Analyze Site Code
Search the site source code for:
- Web API calls (`/_api/`)
- Lookup bindings (`@odata.bind`)
- File uploads (`uploadFileColumn`, `uploadFile`, `upload*Photo`, `upload*Image`)
- `$expand` usage (`$expand`, `buildExpandClause`, `ExpandOption`)
Also check for `.datamodel-manifest.json` in the project root for the authoritative table list.
Build a map of: which tables are referenced in code, which CRUD operations are performed on each, which lookup relationships are used, and which related tables are fetched via `$expand` (these need read permissions too).
### 2.4 Run Shared Schema Validator
Run the shared validator against the existing site:
```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/validate-permissions-schema.js" --projectRoot "<PROJECT_ROOT>"
```
Parse the JSON output and carry the findings into the audit. Treat:
- `error` findings as **critical**
- `warning` findings as **warning**
- `info` findings as **info**
These findings should be included in the final audit report even if the later code/Dataverse analysis also finds additional issues.
After Step 3.1 determines the environment URL, if this audit is running locally with Dataverse access available, rerun the shared validator with live relationship verification enabled and merge any additional findings:
```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/validate-permissions-schema.js" --projectRoot "<PROJECT_ROOT>" --validate-dataverse-relationships --envUrl "<envUrl>"
```
Use this Dataverse-backed relationship validation only for local runs. Do **not** require it in CI or other offline contexts.
---
## Step 3: Analyze & Discover (Dataverse API)
Use deterministic Node.js scripts for all Dataverse API calls. These scripts handle auth token acquisition, HTTP requests, and JSON parsing consistently.
### 3.1 Get Environment URL
```bash
pac env who
```
Extract the `Environment URL` (e.g., `https://org12345.crm.dynamics.com`) and use it as `<envUrl>` in subsequent script calls.
### 3.2 Query Lookup Columns
For each table that has permissions with `create` or `write` enabled, use the lookup query script:
```bash
node "${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/query-table-lookups.js" --envUrl "<envUrl>" --table "<table_logical_name>"
```
The script returns a JSON array of `{ logicalNGuide the user to add a data source, connection, or API connector to a Canvas App via Power Apps Studio, then verify and continue. USE WHEN the user asks to add a data source, add a connection, add an API, add a connector, connect to SharePoint / Dataverse / SQL / Excel / OneDrive / Teams / Office 365, or any similar request to make new data available to the app. DO NOT USE WHEN the user is asking to list or describe existing data sources — call list_data_sources or list_apis directly instead.
Creates or edits a Power Apps Canvas App through the Canvas Authoring MCP coauthoring session. Handles new app generation from requirements, simple inline edits, and complex multi-screen changes with parallel screen builders. Triggers on requests to create, build, generate, modify, update, change, or edit a Canvas App or .pa.yaml files.
Configure the Canvas Authoring MCP server for the current coauthoring session. USE WHEN "configure MCP", "set up MCP server", "MCP not working", "connect Canvas Apps MCP", "canvas-authoring not available", "MCP not configured", "set up canvas apps". DO NOT USE WHEN prerequisites are missing — direct the user to install .NET 10 SDK first.
[DEPRECATED — use canvas-app instead] Generate a complete Power Apps canvas app.
>
Adds Azure DevOps connector to a Power Apps code app. Use when querying work items, creating bugs, managing pipelines, or making ADO API calls.
Adds any Power Platform connector to a Power Apps code app. Generic fallback for connectors not covered by a specific skill.
Adds a data source or connector to a Power Apps code app. Asks what the user wants to accomplish and routes to the appropriate specialized skill.