关于 enable-tables-offline
用于启用 Microsoft Dataverse 表离线支持的技能,面向离线配置维护者。它为指定表设置离线可用和更改跟踪标志,按顺序更新并发布自定义项。
主要功能
- 01启用表的离线可用标志
- 02启用更改跟踪
- 03逐表顺序更新元数据
- 04发布并验证自定义项
- 05跳过已启用的表
适用场景
- 01将表设为可加入移动离线配置
- 02为指定表开启更改跟踪
- 03确认元数据更新并发布
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill enable-tables-offline安装后在 Claude Code 中输入/enable-tables-offline确认已加载。
详细介绍
共享说明:shared-instructions.md — 请先阅读。
参考资料:
- offline-profile-schema.md — 实体字段映射(
IsAvailableOffline、ChangeTrackingEnabled)
启用表的离线功能
在一个或多个 Dataverse 表的 EntityMetadata 上将 IsAvailableOffline=true 和 ChangeTrackingEnabled=true 设置为 true,然后发布自定义项。这是创作者门户中图像 4 所示(“可脱机使用”+“跟踪更改”)的前提条件;如果未同时启用这两项,表就无法添加到 Mobile Offline Profile。
按顺序执行(Dataverse 元数据锁),且具备幂等性:对已启用的表重新运行不会执行任何操作。
调用上下文和根目录绑定
此内部辅助工具始终作为子调用运行。在读取任何项目或执行任何命令之前,
执行 app-working-directory.md。
要求提供所有者的绝对路径 working_dir;如果提供了 --working-dir,它必须
指向同一个原生规范根目录。缺失、相对或冲突的根目录上下文会在访问项目之前返回
NEEDS_CONTEXT;无法访问的目录则返回 BLOCKED。绝不可使用启动时的 cwd,也不可引入其他根目录解析器。
接收 MOBILE_APP_ORCHESTRATING=1、orchestrator: setup-offline-profile、
working_dir、phase、approved_scope 以及提供的答案。保留所选环境 ID/URL/租户,以及精确的表、前提条件和发布许可列表。
此标记不代表已获批准。仅重用与当前离线审批相匹配的批准;范围缺失或变更时,向所有者返回
NEEDS_CONTEXT。对于 --plan-only 或规划阶段的交接,在允许的只读检查后、执行 PUT、发布或写入构件之前,返回拟议的前提条件变更。
门控响应不能解除仅提案模式。
将规范根目录约定应用于每次 shell 调用和文件工具调用。
每次调用都要重新提供绝对路径 PLUGIN_ROOT 和调用上下文;之前的
cd、导出或 shell 变量不会保留。值缺失时返回 NEEDS_CONTEXT;绝不可执行尚未解析的占位符。
所有关联的恢复命令、重新 GET 验证和重试,都必须使用同一根目录、环境和显式租户。只读取绝对应用内路径,
包括 <working_dir>/power.config.json、<working_dir>/memory-bank.md 以及下文所列的清单位置。
工作流
- 验证项目和身份验证 → 2. 确定表列表 → 3. 检查当前状态 → 门控 → 4. 对每个表执行 PUT EntityMetadata → 5. 发布 → 6. 验证 → 7. 总结
步骤 1 — 验证项目和身份验证
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
if [ ! -f power.config.json ] || [ ! -f app.config.js ]; then
echo "BLOCKED: working_dir is not an initialized app" >&2
exit 1
fi
在进行任何发现或修改之前,要求应用的 environmentId 与所有者所选环境一致。使用同一根目录执行此非持久化查找:
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
environment_id=$(node -p "require('./power.config.json').environmentId || ''") || {
echo "BLOCKED: unreadable power.config.json" >&2; exit 1;
}
if [ -z "$environment_id" ] || [ "$environment_id" != "<selected-environment-id>" ]; then
echo "NEEDS_CONTEXT: selected environment does not match working_dir" >&2
exit 1
fi
node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$environment_id" --no-cache --require-tenant
从解析器中获取 <envUrl> 和 <tenantId> 对应的环境 URL和租户 ID。在下方每次辅助工具调用和重试时,都要显式传入此租户;租户上下文缺失或冲突时返回 NEEDS_CONTEXT。
要求 ID、URL 和租户均与所有者的信息一致;绝不可为恢复操作切换账户或环境。若尚未通过身份验证,立即停止。
步骤 2 — 确定表列表
仅使用所有者 approved_scope 中精确列出的表许可列表。$ARGUMENTS 中以逗号
或空格分隔的表列表必须与该列表一致;--working-dir 用于指定根目录上下文,不是表名。表选择缺失或冲突时返回
NEEDS_CONTEXT;明确为空的批准列表表示已验证的无操作。
仅检查 <working_dir>/.datamodel-manifest.json;对于较新的应用,则检查
<working_dir>/docs/plan-artifacts/.datamodel-manifest.json,以验证所选表。清单不代表有权启用其中每一行。不要查找其他应用的清单,也不要擅自扩大许可列表。
步骤 3 — 检查当前状态
开始前打印:
“→ 正在查询 个表的当前 IsAvailableOffline + ChangeTrackingEnabled 状态……”
按顺序检查每个表:
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" GET \
"EntityDefinitions(LogicalName='<table>')?\$select=LogicalName,DisplayName,IsAvailableOffline,ChangeTrackingEnabled,IsCustomizable" \
--tenant-id "<tenantId>"
生成状态表:
| Table | IsAvailableOffline | ChangeTrackingEnabled | IsCustomizable | Needs change? |
|--------------------|--------------------|-----------------------|----------------|---------------|
| cr123_note | false | false | true | YES (both) |
| cr123_visit | true | false | true | YES (track) |
| contact | true | true | true | NO |
**硬性规则:**如果任何表的 IsCustomizable.Value=false,则无法修改该表。将其从变更集中移除,并在 DONE_WITH_CONCERNS 中标记——系统管理的表(大多数 OOB 表)需要使用此技能不支持的管理员解决方案补丁路径。
闸门 — 变更前审批
将步骤 3 中的状态表与所有者已批准的前置条件和发布差异进行比较。如果与当前 Gate 1 审批一致,则沿用该审批,不重复提示。否则,将状态表和 NEEDS_CONTEXT: offline prerequisite approval 返回给负责审批闸门的 /setup-offline-profile。不要扩大范围,也不要覆盖仅提案模式。
计划正文:
The following EntityMetadata changes will be PUT in sequence:
cr123_note → set IsAvailableOffline=true, ChangeTrackingEnabled=true
cr123_visit → set ChangeTrackingEnabled=true (IsAvailableOffline already true)
After all updates, targeted PublishXml will publish only the changed tables.
Tables already in the desired state are skipped (no API call).
如果用户拒绝,则停止。只有在获得对确切变更差异的批准后才能继续。
步骤 4 — 对每个表执行 EntityMetadata PUT
开始前打印:
“→ 正在依次为 个表更新 EntityMetadata(Dataverse 会串行处理元数据写入)……”
**⚠️ 并发规则 — 不得违反。**元数据写入会对每个组织持有独占锁。执行一个 PUT,等待收到 2xx 响应后,再执行下一个。不得批处理或并行调用。规则与
/add-dataverse步骤 5 相同。
对于每个需要变更的表(已处于目标状态的表跳过):
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/update-entity-offline-flags.js" "<envUrl>" \
--table "<table>" \
--offline true \
--tracking true \
--tenant-id "<tenantId>"
该辅助程序:
- 重新读取
EntityMetadata,以获取当前的MetadataId+SchemaName(PUT 请求正文中两者均为必需项;缺少时 Dataverse 会拒绝 PUT)。 - 发送
MSCRM.MergeLabels: true,以保留显示标签(另一种设置会清除标签——切勿使用false)。 - 如果表已处于目标状态,则返回
{ "status": 200, "noop": true, ... }(静默跳过)。 - 对于
IsCustomizable.Value=false的表(由系统管理;必须将其报告为DONE_WITH_CONCERNS),返回{ "status": 200, "skipped": "uncustomizable", ... }。 - 成功更新时返回
{ "status": 204, ... }。 - 自动处理 401 令牌刷新和 429 退避。
**如果辅助程序返回状态 403 PrivilegeCheckFailed:**用户缺少“Customize System”权限。打印表名和缺少的权限,然后停止。
**如果返回状态 400,且提示 ChangeTrackingEnabled cannot be disabled:**忽略——只有在将值从 true 改为 false 时才会触发该错误,而我们绝不会这样做。
每收到一个 204 后打印 ✓ <table>;对于无操作的表打印 ↷ <table> (already enabled);对于跳过的表打印 ⚠ <table> (uncustomizable)。
步骤 5 — 发布自定义项(针对性 PublishXml,失败时回退到 PublishAllXml)
开始前打印:
"→ 正在发布自定义项(对刚刚编辑的实体执行针对性 PublishXml)…"
使用针对性 PublishXml,仅针对实际修改过的实体 — 避免在共享环境中观察到的组织范围限流风暴(0x80071151「已有并发 PublishAll 正在运行」)。经验数据,2026-05-25。
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
# Build the <entities> XML body from the list of tables modified in Step 4
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" POST \
"PublishXml" --tenant-id "<tenantId>" --body '{
"ParameterXml": "<importexportxml><entities><entity><table></entity></entities></importexportxml>"
}'
为步骤 4 中 helper PUT 了标志的每个表替换 <entity>...</entity> 行。未执行任何操作或不可自定义的表应省略。
收到 204 时:成功 — 继续步骤 6。
收到 429 / 0x80071151(「已有并发发布正在运行」)时:通过 dataverse-request.js 的重试逻辑自动退避。如果重试 4 次后仍然失败,则返回 DONE_WITH_CONCERNS: 发布受共享环境瓶颈影响;元数据更改已提交,但 maker portal 需等到下次发布后才会刷新。下游技能(/setup-offline-profile)可以继续 — 元数据层级的写入是持久的。
**仅当针对性调用返回非限流错误(例如 0x80048d19),且所有者另行批准更广泛的发布时,才回退到 PublishAllXml。**仅批准发布指定表,并不代表授权发布无关更改。
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" POST \
"PublishAllXml" --tenant-id "<tenantId>" --body '{}'
超时但操作成功时的处理方式与 /setup-offline-profile 步骤 8 相同:如果客户端超时,但后续 GET 请求显示表的 EntityMetadata 中已设置这些标志,则视为成功。
步骤 6 — 验证
开始前打印:
"→ 正在重新查询 EntityMetadata,以确认标志已设置…"
对每个已修改的表重新运行步骤 3 中的查询。断言每个已更改的行上 IsAvailableOffline=true 且 ChangeTrackingEnabled=true。如果有任何不一致,则返回 BLOCKED — 某些内容静默拒绝了 PUT(极不可能;通常表明托管解决方案层掩盖了非托管更改)。
步骤 7 — 总结
打印:
✓ Offline prerequisites enabled on <N> table(s):
- cr123_note (IsAvailableOffline + ChangeTrackingEnabled set)
- cr123_visit (ChangeTrackingEnabled set; IsAvailableOffline already on)
Skipped (already enabled): contact
Next: return to the current /setup-offline-profile workflow.
在 <working_dir>/memory-bank.md 的 ## Offline profile 下更新时间戳和已验证的表列表。将结果返回给当前所有者;不要启动另一个离线设置工作流。
状态码
技能响应的第一行必须是以下内容之一:
DONE— 所有请求的表现在都已设置两个标志DONE_WITH_CONCERNS: <list>— 跳过了部分表(不可自定义、发布警告等)NEEDS_CONTEXT: <missing>— 无法解析表列表,且用户未提供BLOCKED: <reason>— 身份验证失败、权限检查失败,或 PUT 后验证结果不一致