Onelake Catalog CLI
MicrosoftOfficialPublished by Microsoft
- Skill
- Workflow
- Automation and integrations
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The onelake-catalog-cli skill provides a structured interface for managing the Microsoft Fabric OneLake catalog. It operates through distinct modes for governance auditing and metadata curation, ensuring that actions are performed with appropriate permissions and safety gates. The skill supports tenant-wide admin audits, data-owner governance checks, and item-level metadata curation, including descriptions, tags, and table/column metadata. It enforces strict write-gating and requires explicit owner approval for all changes to ensure data integrity and security.
What it does
- Audits tenant-wide or workspace-specific governance posture.
- Curates item metadata including descriptions, display names, and tags.
- Manages table and column descriptions for items with OneLake Tables.
- Performs guarded remediation for domains, workspace assignments, and capacities.
- Provides dry-run capabilities for governance and remediation tasks.
- Enforces strict write-gates requiring explicit user approval for all changes.
When to use it
- When you need to audit governance posture across a Fabric tenant or specific workspaces.
- When an item owner needs to improve discoverability through metadata curation.
- When a data owner needs to remediate workspace domain, capacity, or tag assignments.
- When a tenant admin needs to perform bulk governance updates or policy enforcement.
Advantages
- Provides a unified, mode-based workflow for both auditing and remediation.
- Enforces safety by requiring explicit approval for all write operations.
- Supports granular, least-privileged access for data owners.
- Includes built-in logic for handling long-running operations and API rate limits.
- Ensures governance findings are actionable and prioritized.
Usage examples
- “Propose a better description for the semantic model Sales Model in the Finance workspace.”
- The agent will read the current item metadata, draft a suggested description based on content, and present it for owner approval before applying the change.
- “Audit our tenant's OneLake catalog governance posture and prioritize the findings.”
- The agent will perform a tenant-wide audit, applying the necessary scope filters, and report findings categorized by pillar with recommended actions.
- “Which workspaces I administer are not assigned to a domain?”
- The agent will identify and list all workspaces within the caller's scope that lack a domain assignment.
- “Show a dry run for assigning these workspaces to the Finance domain, including current assignments.”
- The agent will perform a read-only check to display the current domain assignments and the proposed changes for the specified workspaces.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/microsoft/onelake-catalog-cli/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip onelake-catalog-cli.zip -d .agents/skills
Documentation by Microsoft
Telemetry — MANDATORY. Every
api.fabric.microsoft.comcall must carryx-ms-fabric-skill: onelake-catalog-cli(az rest:--headers "x-ms-fabric-skill=onelake-catalog-cli"), including every LRO poll,fabric_lroand retry. Snippets omit it — add it anyway.
CRITICAL NOTES
To find the workspace ID from its name, one call:
az rest --method get --resource "https://api.fabric.microsoft.com" --url "https://api.fabric.microsoft.com/v1/workspaces" --query "value[?displayName=='<name>'] | [0].id" -o tsv(followcontinuationTokenonly if it isn't on the first page; details in COMMON-CLI.md § Finding Workspaces and Items in Fabric).To find an item's ID, one call: the same on
.../v1/workspaces/{ws}/items?type=<Type>with--query "value[?displayName=='<name>'] | [0].id".Write-gated skill — never call a write API before its gate below has passed. For curation that means the owner reviewed every proposed change and explicitly confirmed — not even a "test" write to check whether a change is allowed or what is already applied.
The item list and Get Item both return an item's
tags. An item with no tags has notagsfield — that absence means untagged.
OneLake Catalog — CLI Skill (mode dispatcher)
One skill for the OneLake catalog. Govern (catalog health, protection and trust: audits and guarded remediation, by permission tier) and curate (an owner improving specific items' discoverability metadata) are modes, each detailed in a reference loaded on demand. This file picks the mode, holds every write gate, and indexes the references.
Mode selection
| Mode | Use when | Load | Writes |
|---|---|---|---|
| curate | An owner wants specific items easier to find: a description, a clearer display name, tags, or table and column descriptions (items with a OneLake Tables folder) — one item, an explicit list, or one named workspace's weakly-described items | references/curate.md | ✅ after the owner approves each suggestion |
| dataowner-audit | A non-admin workspace or domain owner wants governance posture for workspaces they administer (widen to accessible on request; Core API) | references/dataowner-audit.md | ❌ |
| dataowner-remediate | A data owner who is also a domain / workspace / capacity admin fixes a governance finding — single-workspace domain or capacity assignment, workspace tags, refresh, item identity (Core & Power BI APIs, no tenant admin), including dry runs of these | references/dataowner-remediate.md | ✅ self-service |
| admin-audit | A Fabric tenant admin wants tenant-wide governance posture (/v1/admin/*) | references/admin-audit.md; any tenant count starts from admin-audit-scope.md | ❌ |
| admin-remediate | A Fabric tenant admin makes tenant-wide writes — domains, bulk assignment, domain roles, bulk labels, tenant tag definitions, tenant settings | references/admin-remediate.md | ✅ |
Govern is a 2×2 grid — tier (which API surface the caller can reach) × action (audit vs
remediate) — covering the health, protect and trust pillars. Choose the tier by API surface,
not job title: the admin-* modes need the Fabric tenant administrator role (Fabric admin /
Power Platform admin / M365 global admin); domain, capacity and workspace admins who are not
tenant admins live entirely in the dataowner-* modes.
Mode boundary rules
A direct curation request goes straight to curate. Read the target item's current state — don't run a governance audit first. Curation needs neither tenant admin nor workspace Admin; each change has its own permission (see curate.md).
Governance starts with an audit. Never remediate before establishing the current state; audit → remediate within the same tier unless the caller's rights change.
Curate is the only writer of item metadata. Item descriptions and display names, applying or removing an item's tags, and table and column descriptions are written only in curate. Workspace tags stay in dataowner-remediate; tenant tag definitions in admin-remediate.
Govern finds, curate fixes. Govern reports description and tag coverage — presence, with scope, denominator and freshness caveats, not proof the text is accurate; curate judges content and proposes. To fix selected gaps, hand off to curate with: a bounded target (an explicit item list with workspace ID, item ID and type, or one named workspace — never the whole tenant: ask the user to pick), the observed gap with its source and time (a candidate to recheck, not current truth), only the fields the user chose ("fix missing descriptions" = description only), and known access limits and owner contacts. A remediation is done only when curate has verified the write.
Audit modes never write. If a write is asked for in an audit mode, switch explicitly to the matching remediate mode or to curate — don't improvise a write.
A dry run or preflight of a fix loads that fix's remediate mode and stays read-only there — it isn't an audit. Moving one workspace to a domain is
dataowner-remediate; bulk assignment isadmin-remediate.Finding items when the workspace isn't known belongs to
search-consumption-cli. Looking up a workspace or domain by name, or an item by name inside a known workspace, is not discovery: use the lookups in CRITICAL NOTES and don't loadsearch-consumption-clifor it.
⚠️ Known Fabric gap. A domain or workspace admin who is not a tenant admin has no API for their scoped governance posture:
/v1/admin/*rejects them and the Core API can't list a domain's workspaces.dataowner-auditcovers only workspaces the caller can access — say so up front rather than routing into anadmin-*mode that will 401/403.
Terminal write — the step you must not skip
Reading a reference, drafting suggestions or building a dry run is NOT completing a write. Each writing mode ends with the state-changing call(s) below, issued only after the gate for that write passes. If you did not issue it, nothing changed — say so rather than reporting success.
| Mode | Terminal write |
|---|---|
curate | PATCH /v1/workspaces/{ws}/items/{id} (description; display name in a separate call), POST .../items/{id}/applyTags or unapplyTags, and for a table POST https://onelake.table.fabric.microsoft.com/common/v1/{ws}/{item}/schemas/{schema}/tables/{table}/additionalMetadata with the complete set from a fresh read — only for suggestions the owner accepted |
dataowner-remediate | POST /v1/workspaces/{id}/assignToDomain / unassignFromDomain (synchronous 200), assignToCapacity (202 — poll to a terminal state), POST /v1/workspaces/{id}/applyTags / unapplyTags (workspace tags), item identity, semantic model refresh |
admin-remediate | /v1/admin/* writes — domains, bulk workspace assignment, domain roles, labels, tenant tag definitions, tenant settings |
dataowner-audit, admin-audit | none — read-only |
Before reporting a write done, confirm an explicit success (200/201, or a terminal LRO
success for a 202) and read the result back.
Write gates — must pass first
| Write | Mode | Gate |
|---|---|---|
| Any curation write | curate | The owner saw a numbered current → proposed preview of every suggestion and explicitly approved; "apply all" covers only what was shown. Approving an audit or picking a remediation never approves text the owner hasn't seen. |
| Table and column descriptions | curate | A write replaces the table's whole additional metadata: re-read, change only the approved descriptions, send the complete set in the same command, read again. The API has no concurrency check — never claim concurrent edits were preserved. A shortcut table is written on its source — name it and get explicit confirmation. |
| Delete a domain | admin | Check subdomains (parentDomainId) and assigned-workspace counts for the domain and every subdomain; if workspaces would be orphaned, STOP and get explicit confirmation naming them. The API has no cascade-block. See domain-crud.md. |
| Delete a tag definition | admin | Report how many items carry it first — deletion detaches it everywhere with no undo. |
| Bulk-assign workspaces to a domain | admin | Check each target's current domainId and warn before silently overriding an assignment. Dry-run the target list first. |
| Remove a principal from a domain role | admin | Confirm it will not leave the domain ownerless; name the principal being removed. |
| Bulk sensitivity-label change | admin | Dry-run: show the affected items and before/after label, get confirmation. No service principal / managed identity — the call will fail. |
| Write a tenant setting | admin | Read and show the current value, then the proposed value — tenant-wide blast radius. |
| Assign / unassign one workspace to a domain | dataowner | A move is a reassignment — confirm the current domainId and name the domain it leaves. Needs domain contributor and workspace Admin; say which is missing on failure. |
| Reassign item ownership (item identity, preview) | dataowner | Assigns to the caller only; needs Write on the item and its children. Confirm the intended identity. |
| Assign a workspace to a capacity | dataowner | Needs workspace Admin plus capacity Contributor/Admin. 202 is not success — poll to a terminal state. |
| Apply / remove a workspace tag (preview) | dataowner | Needs workspace Admin. Name the workspace and the tags, and confirm. Removing an applied tag is not deleting its definition. |
Don't promise a write that has no API. Endorsement, DLP policies, an owner changing a sensitivity label, and tenant-admin item deletion have no write route — say so and name who can act (no-write-api-escalation.md). A SQL Database's display name is fixed at creation: never send a rename for it, even when the owner asks for one — say it can't be renamed and offer the description and tags instead.
Shared essentials (all modes)
Prerequisites: auth & tokens · REST, pagination, LRO, rate limits · CLI auth recipes ·
az rest(always pass--resource) · OneLake viacurl(Storage-audience token) · OneLake shortcuts.Resolve workspace and item IDs with the one-call lookups in CRITICAL NOTES 1–2.
Keep tool calls few. Each call re-sends the whole conversation, so extra calls are slow and costly. Combine related reads in one script, and don't re-open a doc you've already read.
Read an item's definition in one command that waits for the long-running operation itself (a semantic model usually returns
202) — never poll it in separate calls. It waits as long as Fabric'sRetry-Afterasks (often 20–30 s), so give the command up to 3 minutes: if your shell tool has a wait or timeout setting, raise it rather than letting the command move to the background. Only for types with a definition: Warehouse, SQL Database, SQL analytics endpoint, ML model/experiment and Datamart have none — read their schema instead. PowerShell 7 (bash:fabric_lroin COMMON-CLI.md):$h = @{ Authorization = "Bearer $(az account get-access-token --resource https://api.fabric.microsoft.com --query accessToken -o tsv)"; 'x-ms-fabric-skill' = 'onelake-catalog-cli' } $st = @{ n = 0; end = (Get-Date).AddMinutes(3) } # Waits the full Retry-After (202 and 429); backs off 2-30 s only when the header is missing or invalid. function Wait-RetryAfter($r) { $ra = 0 if (-not [int]::TryParse("$(@($r.Headers['Retry-After'])[0])", [ref]$ra) -or $ra -lt 1) { $ra = [Math]::Min(30, [Math]::Pow(2, ++$st.n)) } if ((Get-Date).AddSeconds($ra) -gt $st.end) { throw "Definition read did not finish within 3 minutes." } Start-Sleep -Seconds $ra } while (($r = Invoke-WebRequest -Method Post -Uri "https://api.fabric.microsoft.com/v1/workspaces/$WS_ID/items/$ITEM_ID/getDefinition" -Headers $h -SkipHttpErrorCheck).StatusCode -eq 429) { Wait-RetryAfter $r } if ($r.StatusCode -ge 400) { throw "getDefinition returned $($r.StatusCode): $($r.Content)" } $def = if ($r.StatusCode -eq 202) { $op = [string]$r.Headers['Location']; $res = $r; $s = '' while ($s -notin 'Succeeded', 'Failed') { Wait-RetryAfter $res; $res = Invoke-WebRequest $op -Headers $h -SkipHttpErrorCheck if ($res.StatusCode -eq 200) { $s = ($res.Content | ConvertFrom-Json).status } elseif ($res.StatusCode -ne 429) { throw "Polling returned $($res.StatusCode): $($res.Content)" } } if ($s -ne 'Succeeded') { throw "Definition read failed: $($res.Content)" } while (($res = Invoke-WebRequest "$op/result" -Headers $h -SkipHttpErrorCheck).StatusCode -eq 429) { Wait-RetryAfter $res } if ($res.StatusCode -ge 400) { throw "Definition result returned $($res.StatusCode): $($res.Content)" } $res.Content | ConvertFrom-Json } else { $r.Content | ConvertFrom-Json } $dir = New-Item -ItemType Directory -Force -Path (Join-Path ([IO.Path]::GetTempPath()) "def-$ITEM_ID") foreach ($p in $def.definition.parts) { $t = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($p.payload)); $f = Join-Path $dir ($p.path -replace '[\\/:]', '_'); Set-Content -LiteralPath $f -Value $t "== $($p.path) ($($t.Length) chars)"; if ($t.Length -le 4000) { $t } else { $t.Substring(0, 4000); "[first 4000 of $($t.Length) chars; full text in $f]" } }A part cut at 4,000 characters is saved in full: read the rest (one call) if what's shown isn't enough.
Use the exact Fabric Admin, Core, Power BI, Graph or OneLake API surface the mode documents; a
401or403is never permission to bypass RBAC.
Rules
MUST
Load exactly one mode reference for the request and follow it end to end; come back to the index below when another procedure is needed. In curate, also read the suggestion guidance before drafting anything, and the table metadata reference before any table or column work.
(curate) Propose exactly what the owner asked for. A specific request gets only that: "add a description" → the item description; "suggest tags" → tags; "describe the table" → the table description only; "describe the columns" → column descriptions only; "describe the item's objects" or "its tables and columns" → both. A general request ("curate this item", "make it more discoverable", "improve its metadata") gets the item's description, name and tags; an item with a OneLake Tables folder also gets its table and column descriptions. If the owner names several items, cover each one, and report each with only the fields it has.
(curate) Check the scope before any call. Curate covers one item, an explicit list of items, or one named workspace at a time. For a tenant-wide request ("all my items", "every workspace"), say plainly that it isn't supported and offer one named workspace or an explicit list; for several named workspaces, ask which to start with. Don't list workspaces or items first.
(govern) State scope, exclusions, pagination completeness, and freshness caveats with every governance statistic.
PREFER
Least-privileged Core or Power BI APIs for data-owner actions instead of requiring tenant-admin rights.
Findings as evidence, consequence, recommended action, priority and effort — not an inventory dump.
Sequencing ownership and access-scope fixes before bulk assignment or labeling.
AVOID
Mutating a tenant from an audit mode, or reporting an asynchronous
202as completion.Inventing write APIs for endorsement, DLP policy, admin item deletion, or third-party item-identity assignment.
(curate) Volunteering anything about table or column descriptions for items without a OneLake Tables folder (semantic models, reports, notebooks, pipelines, dataflows, …). For these items, description, name and tags are the complete list — present them without qualifiers in the preview and whenever you say what the skill can do (e.g. while declining a request, or offering what else you could review next). Don't add a note that table or column descriptions are N/A, don't apply or aren't covered, and don't offer them: the owner didn't ask. Only if they ask, answer that they aren't supported for that item type, then stop and let the owner choose — don't load another skill or draft those descriptions yourself.
(curate) Saying "sub-items" — use the owner's words: "tables" and "columns", or "objects" when speaking generally.
References
Each reference is one hop from this index; after loading one, return here when another is needed.
Curate
Curate — workflow, permission per change, preview format, examples, errors
Suggestion guidance — drafting descriptions, names and tags from content
Tag taxonomy — tenant/domain tag scope and name → ID resolution
Table metadata — table and column descriptions (OneLake table API, preview)
Curation API reference — Update Item, Apply/Unapply Tags, List Tags
Govern — shared
Govern pillars — the three pillars, what "good" looks like, reporting conventions
Governance data sources — verified API field coverage and blind spots
Governance roles — permission tiers, domain/workspace roles, insight refresh lag
Catalog concepts — the entity model and API-backed versus conceptual terms
Govern — modes
Admin audit — tenant-wide read-only governance assessment
Admin audit scope — governable denominator (active workspaces of type Workspace), exclusions, and known blind spots
Admin audit assessment — end-to-end evaluative workflow, prioritization, and deliverable contract
Admin remediate — tenant-wide guarded writes through Admin APIs
Data-owner audit — caller-scoped read-only checks through Core APIs, including a workspace's domain assignment
Data-owner workspace health — empty and inactive workspaces within the caller's scope
Data-owner remediate — least-privileged Core and Power BI writes: moving one workspace to a domain, capacity, workspace tags, refresh, item identity
Govern — admin audit procedures: domain health · workspace health · capacity health · item inventory · item health · protect coverage · trust curation
Govern — admin remediation procedures: domain lifecycle · bulk workspace assignment (tenant admin) · domain roles · tag definitions · item sensitivity labels · domain default labels · trust remediation · no-write escalation
Examples
I'm curating my items for the OneLake catalog. Propose a better description for the semantic model Sales Model in the Finance workspace.Make the lakehouse LSEGDemo more discoverable — describe its tables and columns too.Audit our tenant's OneLake catalog governance posture and prioritize the findings.Which workspaces I administer are not assigned to a domain?Show a dry run for assigning these workspaces to the Finance domain, including current assignments.Find unlabeled items tenant-wide and explain which remediations require a tenant admin versus a data owner.Files
- ATTRIBUTION.mdAdded by AutoGineer883 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md21.5 KiB
- apm.yml345 B
- references/admin-audit-assessment.md10.9 KiB
- references/admin-audit-scope.md5.7 KiB
- references/admin-audit.md14.9 KiB
- references/admin-audit/health-capacity.md7.3 KiB
- references/admin-audit/health-domains.md11.5 KiB
- references/admin-audit/health-item.md13.7 KiB
- references/admin-audit/health-workspaces.md15.4 KiB
- references/admin-audit/item-inventory.md9.1 KiB
- references/admin-audit/protect-labels-dlp.md1.4 KiB
- references/admin-audit/trust-curation.md2.8 KiB
- references/admin-remediate.md17.1 KiB
- references/admin-remediate/domain-assign-workspaces.md7.3 KiB
- references/admin-remediate/domain-crud.md10.5 KiB
- references/admin-remediate/domain-default-label.md2.6 KiB
- references/admin-remediate/domain-roles.md4.5 KiB
- references/admin-remediate/item-sensitivity-label.md2.6 KiB
- references/admin-remediate/no-write-api-escalation.md13.4 KiB
- references/admin-remediate/tags.md1.9 KiB
- references/admin-remediate/trust-curate.md3.4 KiB
- references/catalog-concepts.md7.2 KiB
- references/curate.md19.7 KiB
- references/curate/api-reference.md7.8 KiB
- references/curate/metadata-suggestion-guidance.md10.6 KiB
- references/curate/table-metadata.md9.9 KiB
- references/curate/tag-taxonomy.md3.1 KiB
- references/dataowner-audit.md14.4 KiB
- references/dataowner-audit/health-workspaces.md14.1 KiB
- references/dataowner-remediate.md15.0 KiB
- references/govern-data-sources.md7.9 KiB
- references/govern-pillars.md13.3 KiB
- references/govern-roles.md9.9 KiB
references/admin-remediate.md
<!-- MODE REFERENCE for onelake-catalog-cli (mode: admin-remediate). Loaded on demand by the dispatcher SKILL.md. -->
Routing already happened. The dispatcher SKILL.md is the single source of truth for the 2×2 mode grid, routing rules, and the permission-tier / known-gap notes. This is the admin-remediate mode reference — reached when a Fabric tenant admin performs tenant-wide governance writes via
/v1/admin/*.
CRITICAL NOTES
To find the workspace details (including its ID) from workspace name: list all workspaces and, then, use JMESPath filtering
To find the item details (including its ID) from workspace ID, item type, and item name: list all items of that type in that workspace and, then, use JMESPath filtering
These are Admin APIs (
/v1/admin/*) — the caller must be a Fabric tenant administrator. A Domain admin is NOT sufficient and will get403; that is the API contract, not a bug. (Not here: item descriptions, display names and item tags are written incuratemode; workspace tags and single-workspace assignment live in thedataowner-remediatemode.)Deleting a domain never deletes workspaces or their data. It only removes the domain's grouping/governance attribute from the workspace — but a domain with a subdomain that has assigned workspaces has a real, non-obvious safety gap between the Admin Portal (which warns you) and the raw REST API (which does not). Read admin-remediate/domain-crud.md § Deleting a Domain before calling Delete Domain.
Three different token audiences. Fabric admin/core APIs use
https://api.fabric.microsoft.com; Power BI label and refresh APIs usehttps://analysis.windows.net/powerbi/api. Using the wrong one returns401/403that looks like a permissions problem but isn't.Endorsement and DLP policies have NO public write API. Never fabricate one — see
admin-remediate/no-write-api-escalation.md.
OneLake Catalog Govern — Admin Remediate (write) CLI Skill
Contents
Prerequisite Knowledge
Reference Files (load on demand)
Must/Prefer/Avoid
Gotchas and Troubleshooting
Tenant-wide write operations for Fabric governance across all three Govern pillars: health (domains, subdomains, bulk domain assignment, tag definitions), protect (sensitivity labels, domain default labels), and trust/curate (certification enablement). Object-scoped workspace capacity assignment, workspace tags, refresh, and item identity belong to dataowner-remediate; item descriptions, display names and item tags belong to curate.
This dispatcher holds only what applies to every remediation — the prerequisites, the Must/Prefer/Avoid rules, and the cross-cutting troubleshooting table. Each concrete procedure and its procedure-specific gotchas live in a topic file under admin-remediate/ — load the one that matches the task, not all of them.
Prerequisite Knowledge
govern-roles.md— read first: Fabric admin vs. Domain admin vs. Domain contributor, subdomain admin inheritance, default-domain auto-assignment behaviorcatalog-concepts.md— entity model and relationship semantics; which concepts are API-backedRepository
common/COMMON-CORE.md— Fabric REST API patterns, authRepository
common/COMMON-CLI.md— CLI implementation (az rest, quick reference)
Reference Files (load on demand)
Read the one matching the request. Each carries its own worked example and procedure-specific gotchas; the cross-cutting Gotchas table below applies regardless of which you load.
| File | Read it when the task is… | Pillar / tier |
|---|---|---|
| domain-crud.md | Create / update / delete a domain or subdomain. Read before any delete — the portal-vs-API safety gap | Health |
| domain-assign-workspaces.md | Assign / unassign workspaces to a domain — three methods, choosing between them, override behavior, dry-run first | Health |
| domain-roles.md | Assign domain admins / contributors (fixes ownerless domains); the role model; narrowing over-broad scope | Health |
| tags.md | Create / update / delete tenant tag definitions (admin-only); applying item tags is curate mode, workspace tags dataowner-remediate | Health |
| item-sensitivity-label.md | Apply / remove item sensitivity labels — genuinely admin-only, no SPN support, 25 req/hr | Protect |
| domain-default-label.md | Set a domain's defaultLabelId — stops the backlog regrowing; never labels dormant items | Protect |
| trust-curate.md | Enable certification / designate certifiers; where item descriptions (curate) and refresh (data-owner) live | Trust / curate |
admin-remediate/no-write-api-escalation.md | Read before promising any remediation — what has no write API (endorsement, DLP, item delete/ownership, workspace roles) and how to turn a finding into a named contact list | Cross-cutting |
What doesn't live here: item descriptions, display names and item tags are written in curate mode — hand off selected gaps per the dispatcher's mode boundary rules (bounded target, chosen fields only). Workspace tags, triggering a semantic-model refresh, assigning a single workspace to a domain, and reassigning item ownership (item identity) are dataowner-remediate — all need only workspace/item rights, not tenant admin. See dataowner-remediate.md.
Must/Prefer/Avoid
MUST DO
Read admin-remediate/domain-crud.md before any delete operation — the REST API has no cascade-block or force parameter for domains with subdomains/assigned workspaces; the safety check is the agent's responsibility, not the API's.
Before deleting any domain: check for subdomains (
parentDomainIdmatch) and check assigned-workspace counts for the domain and every subdomain viaGET /v1/admin/domains/{id}/workspaces. If any workspaces would be orphaned, get explicit user confirmation naming the affected workspaces and domains before callingDELETE.Before bulk-assigning workspaces, check each target workspace's current
domainIdand warn the user if it will silently override an existing assignment.Use
preview=falseon Create Domain and Update Domain calls — it's a mandatory query parameter despite the API no longer being preview-only.Dry-run every bulk write. For label changes, tag deletions, and domain updates, show the user the exact affected item list and the before/after value, and get confirmation before executing.
Check what actually has a write API before promising a remediation — see
admin-remediate/no-write-api-escalation.md. Endorsement and DLP policies cannot be set via REST.When a fix is outside tenant-admin reach, name who can do it. Item deletion, item ownership and workspace role changes are not admin-writable. Never report "cannot be automated" on its own — produce the contact list, see
admin-remediate/no-write-api-escalation.md§ Route a Finding.Read tenant settings before writing them — show the current value, then the proposed value. Tenant settings have tenant-wide blast radius.
PREFER
Reassign before delete — if the user wants to remove a domain but keep its workspaces governed, assign those workspaces to another domain first, then delete.
Confirm subdomain admin inheritance — since subdomains have no admins of their own, don't attempt to set subdomain-specific admins; direct the user to the parent domain's admin settings instead.
Domain default sensitivity label over bulk relabeling — setting
defaultLabelIdon a domain stops the backlog regrowing; bulksetLabelsclears the existing backlog. Do both, in that order. Note the default label never touches dormant unlabeled items.Fix the cause, not the symptom — a repeatedly stale model needs its schedule or data source fixed, not a manual refresh each time.
Batch within documented limits — 2,000 items per label call, 100 workspaces per scan, 10 tags per item.
The least-privileged path — item metadata fixes go to curate (item rights) and workspace fixes to dataowner-remediate (workspace rights); don't require the user to obtain tenant admin for item-level fixes.
AVOID
Do NOT call
DELETE /v1/admin/domains/{domainId}without first checking for subdomains and assigned workspaces — this skill's whole value is closing the gap the raw API leaves open.Do NOT assume assignment operations warn on override — they don't; check current assignment status yourself.
Do NOT delete a tag without reporting how many items carry it — deletion detaches it everywhere, and there is no undo.
Do NOT attempt sensitivity-label writes with a service principal or managed identity — neither labeling API supports them; the call will fail.
Do NOT write item descriptions, display names or item tags here — tenant admin grants no item write. Hand selected gaps to curate, which drafts from the item's content and gets the owner's approval for each suggestion.
Do NOT invent an endorsement or DLP-policy endpoint. None exists.
Do NOT confuse this skill with the read-only
admin-auditmode (diagnostics only, no writes) ordataowner-auditmode (self-service reads on the caller's own workspaces).
Gotchas and Troubleshooting
Cross-cutting symptoms across every remediation. Procedure-specific gotchas live in the matching topic file.
| Symptom | Cause | Fix |
|---|---|---|
403 Forbidden on any write call | Caller lacks the Fabric tenant administrator role — a domain or capacity admin is not sufficient for /v1/admin/* | Confirm the signed-in identity holds the Fabric admin role. A domain admin has no admin-API path to these writes (see the dispatcher's known-gap note). |
EntityConflict on Create Domain | Display name already exists tenant-wide | Domain names must be unique across the whole tenant, not just per parent |
EntityNotFound on Create Domain | Bad parentDomainId | Verify the parent domain ID exists via GET /v1/admin/domains first |
| Workspace assignment silently changed domain | Assign APIs override an existing assignment when the override tenant setting is enabled | Check domainId before assigning and warn the user; see domain-assign-workspaces.md § Choosing a bulk-assignment method |
| Deleted a domain and workspaces "disappeared" from governance view | Expected — deletion unassigns workspaces, it does not delete them or their data | Reassign the orphaned workspaces to a new/existing domain; nothing was lost except the domain attribute |
| Bulk assign returned success but some workspaces did not move | The tenant setting "Allow tenant and domain admins to override workspace assignments (preview)" is disabled, so already-assigned workspaces were silently skipped | Re-read /v1/admin/domains/{id}/workspaces and report the actual delta. To move them, either enable the setting or unassign from the old domain first |
| Assigned by workspace admin, but new workspaces those people create aren't in the domain | Expected — assignWorkspacesByPrincipals is point-in-time, not a standing rule | Ongoing auto-assignment requires a default domain (portal-only, no API) |
| Assigned by capacity, but workspaces later moved onto that capacity aren't in the domain | Expected — same point-in-time semantics | Re-run the bulk assignment periodically, or use a default domain |
| Personal workspaces not picked up by bulk assignment | Expected and correct — both bulk methods exclude My workspaces, which can never hold a domainId | Not a gap; do not report it as one |
202 Accepted from a bulk assign, then reporting success immediately | Both bulk methods are long-running operations | Poll the Location URL to a terminal state before reporting anything |
| Unsure if a domain has subdomains before deleting | Domains list doesn't nest subdomains visually | Filter GET /v1/admin/domains results by parentDomainId == <target> |
| Tried to set a subdomain-specific admin | Subdomains inherit admins from their parent domain | Set admins on the parent domain instead — see domain-roles.md § Role Model |
UnsupportedPrincipalTypeForDomainAdminAssignment | Tried to assign EntireTenant (or another unsupported type) as a domain Admin | EntireTenant is valid for Contributors only; use a User or Group for Admin |
PrincipalWithDomainRoleAssignmentAlreadyExists | Principal already holds that role on the domain | Not an error condition — GET .../roleAssignments first and skip existing principals |
| Domain role assign call rejects the body | type must be plural — "Admins" / "Contributors", not "Admin" | Fix the payload casing/plurality |
Removed EntireTenant contributor and users lost access | Contributor scope was the only thing letting them assign workspaces | Assign the intended group before unassigning EntireTenant |
| Domain contributor still can't assign a workspace | Domain contributor is useless without workspace Admin on that workspace | Grant the workspace Admin role, or have a workspace admin perform the assignment |
401/403 on api.powerbi.com calls while Fabric calls succeed | Wrong token audience — label and refresh APIs need https://analysis.windows.net/powerbi/api | Acquire a second token for that resource; the Fabric token will not work |
| Label write fails under automation | Neither bulkSetLabels nor informationprotection/setLabels supports service principals or managed identities | Run interactively as a signed-in Fabric admin; there is no unattended path |
| Label write rejected as unknown label | The label is not in the calling admin's own Purview label policy | Use a label assigned to the caller's policy, or have Purview grant it |
429 / throttling on bulk labeling | Power BI variant allows only 25 requests/hour | Batch up to 2,000 items per request and pace the calls |
| Tag deleted and it vanished from many items | Expected — deleting a tag detaches it everywhere | No undo; recreate the tag and re-apply. Always report the applied-item count before deleting |
| Refresh rejected on shared capacity | Shared capacity allows 8 refreshes/day and only notifyOption | Move to Fabric/Premium capacity for enhanced refresh, or wait for the quota to reset |
| User asks to certify an item via API | No public REST API exists for setting endorsement | Enable certification via tenant settings, then endorse in the portal — see admin-remediate/no-write-api-escalation.md |
| User asks to create a DLP policy | Not available in Fabric REST | Microsoft Purview portal |
PATCH domain rejected | Missing the mandatory ?preview=false query parameter | Append it — required on Create and Update Domain |
| Domain default label set successfully but nothing gets labeled | Tenant setting "Domain admins can set default sensitivity labels for their domains (preview)" is not enabled | Enable it before debugging the call |
| Domain default label set, but old unlabeled items stay unlabeled | Expected — the default applies only to new items and to existing unlabeled items when updated and saved. Dormant items are never touched | Use bulk setLabels to clear the backlog, and the default label to stop it regrowing |
| Domain default label didn't override an existing label | Manually applied labels are never overridden; auto/policy labels only when lower priority | Working as designed — relabel explicitly if required |
| Domain default label not applying via deployment pipelines or Git | Documented limitation — neither is supported | No workaround; label explicitly in those flows |
DELETE /v1/admin/items/{id} returns 404 | No admin-tier item write route exists. Not a permission problem — the route is not real. | Use the core route as someone with workspace Contributor+, or hand off. Never retry with a different admin path. |
GET/DELETE on /v1/workspaces/{id}/items returns 401 for a tenant admin | Tenant admin does not confer workspace membership. Live-verified. | Have a workspace admin act, or take over the workspace in the portal first — an auditable permission change, never silent. |
| User asks "who owns this item so I can ask them to delete it?" | Legitimate and answerable | admin-remediate/no-write-api-escalation.md § Route a Finding — workspace admins first, creator second. Do not present the creator as an authority. |
| Assign-identity call returns 202 and nothing seems to change | It is a long-running operation | Poll the Location header URL; inspect the per-item assignmentStatus array. A failed child halts the whole operation. |
.../lakehouses/{id}/identities/default/assign errors | Documented known issue — the type-qualified path is broken | Use the generic /items/{id}/identities/default/assign?beta=true form. |
| User asks to assign an item identity to another person or SPN | Not supported — the body is {"assignmentType":"Caller"}, which claims ownership for the caller | The target identity must make the call itself, with Write on the item and all children. Hand them the command; do not run it as admin. |
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Microsoft
- Publisher
- Microsoft (Official)
- Source
- microsoft/skills-for-fabric · skills/onelake-catalog-cli · commit f8fac11
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- microsoft/skills-for-fabric
AutoGineer is not affiliated with or endorsed by Microsoft.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download onelake-catalog-cli.zip