dsh-d365-kit 0.34.1 → 0.34.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +318 -308
  2. package/CHANGELOG.zh-CN.md +317 -307
  3. package/INSTALL.md +94 -94
  4. package/INSTALL.zh-CN.md +93 -93
  5. package/LICENSE +21 -21
  6. package/README.md +336 -327
  7. package/README.zh-CN.md +336 -327
  8. package/client.js +1818 -1818
  9. package/cordis.patch.yml +44 -44
  10. package/docs/en/architecture.md +172 -172
  11. package/docs/en/checks.md +184 -184
  12. package/docs/en/installation.md +151 -151
  13. package/docs/en/permissions.md +161 -161
  14. package/docs/en/scenarios.md +202 -202
  15. package/docs/en/tools.md +665 -665
  16. package/docs/en/troubleshooting.md +131 -131
  17. package/docs/zh/architecture.md +172 -172
  18. package/docs/zh/checks.md +184 -184
  19. package/docs/zh/installation.md +151 -151
  20. package/docs/zh/permissions.md +161 -161
  21. package/docs/zh/scenarios.md +202 -202
  22. package/docs/zh/tools.md +665 -665
  23. package/docs/zh/troubleshooting.md +131 -131
  24. package/examples/prompts.en.md +206 -206
  25. package/examples/prompts.zh-CN.md +206 -206
  26. package/examples/waivers.example.json +20 -20
  27. package/icon.svg +6 -6
  28. package/index.js +139 -139
  29. package/lib/auth.js +181 -181
  30. package/lib/client.js +496 -496
  31. package/lib/code-check.js +549 -549
  32. package/lib/config.js +323 -323
  33. package/lib/contract-history.js +49 -49
  34. package/lib/contract.js +583 -583
  35. package/lib/csharp-check.js +493 -493
  36. package/lib/data-migrate.js +1318 -1318
  37. package/lib/data-policy.js +78 -78
  38. package/lib/error-codes.js +80 -80
  39. package/lib/gitlab.js +161 -161
  40. package/lib/health.js +205 -205
  41. package/lib/migrate.js +732 -732
  42. package/lib/preflight.js +116 -116
  43. package/lib/refs.js +191 -191
  44. package/lib/resources.js +320 -320
  45. package/lib/retention-defaults.js +17 -17
  46. package/lib/retention.js +384 -384
  47. package/lib/runtime.js +232 -232
  48. package/lib/settings-http.js +512 -512
  49. package/lib/settings-store.js +371 -371
  50. package/lib/snapshot.js +149 -149
  51. package/lib/tool-code-check.js +133 -133
  52. package/lib/tool-configure.js +169 -169
  53. package/lib/tool-contract.js +376 -376
  54. package/lib/tool-data-sync.js +559 -559
  55. package/lib/tool-data-write.js +203 -203
  56. package/lib/tool-data.js +282 -282
  57. package/lib/tool-diff.js +484 -484
  58. package/lib/tool-environments.js +106 -106
  59. package/lib/tool-flows.js +540 -540
  60. package/lib/tool-health.js +127 -127
  61. package/lib/tool-layers.js +497 -497
  62. package/lib/tool-metadata.js +417 -417
  63. package/lib/tool-migrate.js +102 -102
  64. package/lib/tool-refs.js +206 -206
  65. package/lib/tool-reports.js +299 -299
  66. package/lib/tool-sync.js +430 -430
  67. package/lib/tool-write.js +563 -563
  68. package/lib/waivers.js +83 -83
  69. package/lib/write-actions.js +1374 -1374
  70. package/lib/write-policy.js +199 -199
  71. package/lib/write-store.js +167 -167
  72. package/locale/en.json +68 -68
  73. package/locale/zh.json +68 -68
  74. package/package.json +2 -2
  75. package/skills/d365-troubleshooting/SKILL.md +115 -115
package/README.zh-CN.md CHANGED
@@ -1,327 +1,336 @@
1
- # dsh-d365-kit(D365 工具箱)
2
-
3
- **[English](README.md)** | 简体中文
4
-
5
- Dynamics 365 CE / Dataverse 的**开发与部署助手**,作为 [DeepSeek Harness](https://github.com/deepseek-ai) 的 bundle 安装。
6
- 它把一个真实的 D365 组织变成 agent 能直接查的东西:元数据、解决方案层、快照差异、引用关系、迁移风险、代码改动的影响面,以及受控的写入。
7
-
8
- > 十九个工具、一个设置页。默认只读:勾选什么就只做什么,元数据也由「读取元数据」这一项控制(默认开启)。
9
-
10
- ```
11
- 你:DEV 的 account 上 contoso_customertier 这个字段,现在还有哪些表单和视图在用它?
12
- agent:表单 17 张、视图 64 个(列 62 / 筛选 50)、业务流程 0 个 …
13
- ```
14
-
15
- ---
16
-
17
- ## 它解决什么问题
18
-
19
- D365 项目的日常摩擦,大多不是"不会写代码",而是**环境之间的信息不对称**:
20
-
21
- | 问题 | 这个插件怎么答 |
22
- | --- | --- |
23
- | 这个解决方案发到 SIT,会不会把别的解决方案的定制压掉? | `d365_migrate` 逐组件查层,列出会被遮蔽的解决方案、缺失的组件、会丢的选项值 |
24
- | 为什么两个环境的同一张表单不一样? | `d365_layers` 告诉你是谁覆盖了它,`d365_diff` 给出字段级差异 |
25
- | 删这个字段会不会出事? | `d365_refs` 反查表单 / 视图 / 流程 / 插件步骤,`d365_data` 看还有多少条记录在用 |
26
- | 这个 MR 发布到 UAT 能跑起来吗? | `d365_code_check` 把 JS 映射到 Web 资源与表单、把 C# 映射到程序集/类型/步骤/镜像 |
27
- | 上游改了插件,下游跟上了吗? | `d365_contract` 把上游注册当契约,逐条比对下游,带豁免与趋势 |
28
- | 现在能发布吗? | `d365_health` 看挂起的导入/发布与失败作业,写入前的预检查用的是同一份数据 |
29
- | 补一个字段 / 选项值 / 视图列? | `d365_write` 生成计划 → 人在对话里确认 → 才写入,事后可查审计 |
30
-
31
- ---
32
-
33
- ## 功能一览
34
-
35
- ### 连接与环境
36
-
37
- | 工具 | 用途 |
38
- | --- | --- |
39
- | `d365_envs` | 环境清单、凭据是否齐全;`check: true` 时真实连一次 |
40
- | `d365_configure` | 增删改环境(URL、租户、ClientId、密钥)、测连通性 |
41
- | `d365_health` | 挂起/失败的后台作业、正在进行的导入发布、最近安装的解决方案 |
42
-
43
- ### 元数据与解决方案层
44
-
45
- | 工具 | 用途 |
46
- | --- | --- |
47
- | `d365_metadata` | 19 类资源:实体、字段、关系、表单、视图、工作流、业务规则、插件、Web 资源、解决方案、组件、Custom API、站点地图、选项集 |
48
- | `d365_layers` | `msdyn_componentlayer`:某组件被哪些解决方案覆盖过、谁在最上层、当前生效的是哪一层 |
49
-
50
- ### 快照与对比
51
-
52
- | 工具 | 用途 |
53
- | --- | --- |
54
- | `d365_sync` | 把环境的元数据拉成本地快照,逐资源记录「完整 / 被截断 / 失败」 |
55
- | `d365_diff` | 两份快照的字段级差异(新增、删除、修改),带噪声过滤与快照过期提示 |
56
-
57
- ### 影响面与数据
58
-
59
- | 工具 | 用途 |
60
- | --- | --- |
61
- | `d365_refs` | 反查:字段 → 表单/视图/流程;Web 资源 → 表单与事件;程序集 → 类型与步骤 |
62
- | `d365_data` | 业务记录 count / group by / sample(需授权 `data.read`) |
63
- | `d365_data_write` | 新建或修改一条业务记录,对话确认后执行(需 `data.write`) |
64
- | `d365_data_sync` | 环境之间镜像记录(保持 GUID、解析 lookup、报告冲突),或按 id 清单批量改一个字段 |
65
-
66
- ### 写入
67
-
68
- | 工具 | 用途 |
69
- | --- | --- |
70
- | `d365_write` | 选项集增/改/删值、新增/改/删字段、改表显示名、增删系统视图列;`plan-*` 只出计划,`execute` 必须人工确认 |
71
-
72
- ### 迁移与检查
73
-
74
- | 工具 | 用途 |
75
- | --- | --- |
76
- | `d365_migrate` | 解决方案迁移风险评估:层遮蔽、组件缺失、选项值丢失、版本与受管状态 |
77
- | `d365_contract` | 契约矩阵与漂移:程序集、插件类型、步骤、表单库、Handler、站点地图、选项值;带豁免与趋势 |
78
- | `d365_code_check` | 读 GitLab MR,JS/C# 改动 → 目标环境核对,输出阻断 / 警告 / 人工确认 |
79
-
80
- ### 排查
81
-
82
- | 工具 | 用途 |
83
- | --- | --- |
84
- | `d365_trace` | 插件跟踪日志:谁跑了、抛了什么、按签名归并;messageblock 里的凭据会屏蔽(需 `data.read`) |
85
- | `d365_invoke` | 真正调一次 Dataverse 消息,看状态码与响应体;GET function 需 `data.read`,POST action 需 `message.invoke` 且每次确认 |
86
- | `d365_flows` | Power Automate 云流(`workflow` 表 `category = 5`):目录、单条流程的触发器/动作/连接器、哪些流程会碰某张表 |
87
-
88
- ### 运维
89
-
90
- | 工具 | 用途 |
91
- | --- | --- |
92
- | `d365_reports` | 本机产物与占用、按保留策略清理(默认预演)、压缩快照 |
93
-
94
- ---
95
-
96
- ## 设置页
97
-
98
- DSH Web UI 的「设置 → D365 工具箱」,六个标签页:
99
-
100
- | 标签 | 内容 |
101
- | --- | --- |
102
- | 环境 | 环境清单、测试连接、默认环境 |
103
- | 权限 | 按环境勾选能力(读业务数据 / 写入类)、变更默认解决方案、复制到其它环境 |
104
- | 计划 | 待确认的写入计划、最近的变更记录与发布结果(可重新发布) |
105
- | 数据 | 每类产物的文件数 / 体积 / 保留策略,预演并清理,压缩快照 |
106
- | GitLab | 仓库地址、默认项目、只读令牌(`read_api`) |
107
- | 常规 | 快照保留份数、默认行数上限、请求超时 |
108
-
109
- 界面语言跟随 DSH(中文 / English)。环境清单与 `d365_configure` 走同一份存储代码,界面和 agent 看到的一定一致。
110
-
111
- ---
112
-
113
- ## 安装
114
-
115
- 前置:DSH 桌面版;机器能访问 `*.dynamics.com`;一个只读应用用户(ClientId + 密钥)。
116
-
117
- ```bash
118
- # 从 npm 安装(最短,可升级;包发布到 npm 或内网 registry 后可用)
119
- plugin_manager install_bundle target="dsh-d365-kit@0.34.1"
120
-
121
- # 从 Git 安装(不需要 registry,可钉 tag)
122
- plugin_manager install_bundle target="git+https://<your-git>/<group>/dsh-d365-kit.git#v0.34.1"
123
-
124
- # 或从本地目录安装(link,改代码立刻生效)
125
- plugin_manager install_bundle target="D:\path\to\dsh-d365-kit"
126
- ```
127
-
128
- `dsh-d365-kit@<版本>` 是从 **npm registry** 解析的;只发到 GitHub 时,用第二条的 `git+https://` 形式装。仓库里带 `.github/workflows/publish.yml`,配好 `NPM_TOKEN` 后推 `v*` tag 就会自动发 npm。
129
-
130
- 装完**重启一次 DSH**,Web 客户端才会把设置页代码加载进模块图。
131
-
132
- 然后:设置 → D365 工具箱 → 环境 → 添加环境(key、URL、租户、ClientId、密钥)→ 测试连接 → 保存。
133
- 默认只读;要读业务记录,去「权限」勾「读取业务数据」。
134
-
135
- 完整步骤、凭据解析顺序、升级与卸载见 [docs/installation.md](docs/zh/installation.md)。
136
-
137
- ---
138
-
139
- ## 典型用法
140
-
141
- ### 1. 发布前评估一个解决方案
142
-
143
- ```
144
- 这个解决方案发到 SIT 和 UAT 有什么风险?
145
-
146
- d365_migrate action=assess source=dev solution=ContosoBase targets=["sit","uat"]
147
- ```
148
-
149
- 报告回答:目标有没有这个解决方案、源版本是不是更高、每个组件的层会被谁压住(列出被遮蔽的解决方案)、选项集会不会丢值。落在 `.d365/reports/migration-*.md`。
150
-
151
- ### 2. 这个字段能删吗
152
-
153
- ```
154
- account.contoso_customertier 还有谁在用?顺便看下还有多少条记录带着值。
155
-
156
- d365_refs kind=field entity=account attribute=contoso_customertier
157
- d365_data action=group entity=account field=contoso_customertier
158
- ```
159
-
160
- ### 3. 两个环境为什么不一样
161
-
162
- ```
163
- d365_sync environments=["dev","sit"]
164
- d365_diff base=dev head=sit resources=["forms","views","attributes"]
165
- d365_layers component=Account componentType=SystemForm
166
- ```
167
-
168
- ### 4. 检查一个 MR 能不能发到 UAT
169
-
170
- ```
171
- d365_code_check mergeRequest="https://gitlab.example.com/contoso/powerapps/-/merge_requests/7759/diffs" targets=["uat"]
172
- ```
173
-
174
- JS 改动会映射到 Web 资源与表单,检查读取的字段是否在表单上、删除的函数是否仍被 Handler 引用;
175
- C# 改动会核对程序集版本、插件类型、步骤、step 镜像与过滤属性。静态判不了的进「人工确认」清单。
176
-
177
- ### 5. 补 36 个税号选项(写入全流程)
178
-
179
- ```
180
- d365_write action=plan-add-options environment=dev optionSet=contoso_taxcategoryos labels=["AD3|Andorra: Tax Register Number", ...]
181
-
182
- (agent 返回计划与操作列表)
183
- 执行 mw04aul6-1ci6aa
184
- ```
185
-
186
- 第二步会在对话里弹确认卡片,点「批准执行」才写入;写入后只发布受影响的那个选项集,不重算整个组织。
187
-
188
- ### 6. 上游插件改了,下游还缺什么
189
-
190
- ```
191
- d365_contract action=drift source=dev targets=["sit","uat"] forms=true
192
- ```
193
-
194
- 更多可直接复制的说法见 [examples/prompts.md](examples/prompts.zh-CN.md) 与 [docs/scenarios.md](docs/zh/scenarios.md)。
195
-
196
- ---
197
-
198
- ## 权限模型
199
-
200
- 默认**只读**。能力按环境授权,存在 `d365.config.json` 的 `write.environments`;设置页里每个环境单独一块,用分隔线隔开:
201
-
202
- ```json
203
- {
204
- "write": {
205
- "capabilityVersion": 2,
206
- "environments": {
207
- "dev": ["metadata.read", "data.read", "optionValue.add", "attribute.add"],
208
- "sit": ["metadata.read", "data.read"]
209
- },
210
- "solutionUniqueName": "ContosoBase"
211
- }
212
- }
213
- ```
214
-
215
- 环境没有条目 = 还没配过,默认只开 `metadata.read`;条目是空数组 = 全关。
216
-
217
- | 能力 | 对应操作 | 作用 |
218
- | --- | --- | --- |
219
- | `metadata.read` | 元数据 `GET` | 读表 / 字段 / 表单 / 视图 / 插件 / 层(默认开启) |
220
- | `data.read` | 业务数据 `GET` | 读业务记录;不授权时读不到表里的记录 |
221
- | `data.write` | `POST` / `PATCH` | 新建或修改业务记录(不含删除) |
222
- | `optionValue.add` | `InsertOptionValue` | 新增选项值(全局或字段本地) |
223
- | `optionValue.updateLabel` | `UpdateOptionValue` | 改选项标签 |
224
- | `optionValue.delete` | `DeleteOptionValue` | 永久删除选项值(高危) |
225
- | `attribute.add` | `CreateAttribute` | 新增字段 |
226
- | `attribute.update` | `UpdateAttribute` | 改字段显示名 / 描述 / 必填级别 |
227
- | `attribute.delete` | `DeleteAttribute` | 永久删除字段及其数据(高危) |
228
- | `entity.update` | `UpdateEntity` | 改表显示名与描述 |
229
- | `view.columns` | `UpdateSavedQuery` | 增删系统视图的列 |
230
- | `layer.remove` | `RemoveActiveCustomizations` | 移除组件最上面的未受管自定义层(高危) |
231
-
232
- 写入是两步:`plan-*` 只读生成计划 → 人在对话(或设置页)确认后 `execute`。执行前会查环境是否正在导入/发布,忙则拒绝;每次执行逐条记进 `.d365/changes/`,计划有 `pending → running → done/failed` 状态,重跑不会重复提交。
233
-
234
- 判定收在 `lib/client.js` 一处:先看是不是元数据请求(要 `metadata.read`),其余 `GET` 一律按业务数据拦截(要 `data.read`),非 `GET` 的写还要 `data.write`。拦截发生在取令牌之前,新增工具绕不过这三道闸。
235
-
236
- 详见 [docs/permissions.md](docs/zh/permissions.md)。
237
-
238
- ---
239
-
240
- ## 本地产物
241
-
242
- ```
243
- <工作区>/
244
- d365.config.json # 环境清单与工具参数(可进 Git)
245
- d365.secrets.json # 客户端密钥(明文,别提交)
246
- .d365/
247
- snapshots/<env>/<id>/ # 元数据快照 + manifest
248
- diffs/ # 对比报告
249
- reports/ # 迁移、契约、代码检查、历史趋势
250
- query/ # 查询留证、数据写入审计
251
- pending-writes/ # 待确认计划
252
- changes/ # 已执行的变更与发布结果
253
- waivers.json # 契约豁免
254
- ```
255
-
256
- `.d365/` 自带 `.gitignore`(内容 `*`)。保留策略默认:快照 2 份/30 天、报告 50/90、diff 20/30、query 100/7、changes 200/180,写产物后自动清理,`waivers.json` 与待确认计划永不清理。
257
-
258
- ---
259
-
260
- ## 文档
261
-
262
- | 文档 | 内容 |
263
- | --- | --- |
264
- | [docs/installation.md](docs/zh/installation.md) | 安装、首次配置、凭据、升级、卸载 |
265
- | [docs/tools.md](docs/zh/tools.md) | 19 个工具的参数、返回与示例 |
266
- | [docs/scenarios.md](docs/zh/scenarios.md) | 8 个真实场景的完整走法 |
267
- | [docs/permissions.md](docs/zh/permissions.md) | 能力表、写入流程、预检查、安全边界 |
268
- | [docs/checks.md](docs/zh/checks.md) | 迁移评估、契约漂移、代码检查的规则与置信度 |
269
- | [docs/troubleshooting.md](docs/zh/troubleshooting.md) | 常见错误码与排查 |
270
- | [skills/d365-troubleshooting/SKILL.md](skills/d365-troubleshooting/SKILL.md) | Agent skill:从跟踪日志到复现调用的排查流程(插件自己注册,不用复制) |
271
- | [docs/architecture.md](docs/zh/architecture.md) | 模块结构、数据流、如何加一个工具 |
272
- | [CHANGELOG.md](CHANGELOG.zh-CN.md) | 版本记录 |
273
-
274
- ---
275
-
276
- ## 已知边界
277
-
278
- - 不采 Ribbon 与 Power Automate 云流。
279
- - `attributes` 按实体逐个请求,实体多时请求量等于实体数;用 `entities` 缩小范围。
280
- - 元数据表基本没有增量游标,每次同步都是全量;增量只能「跑第二次然后 diff」。
281
- - `d365_layers` 依赖 `msdyn_componentlayer` 虚拟表:必须同时给组件 id 与类型,只给名字返回 0 行。
282
- - 组件类型 36 / 50 / 70(报表、图表类)在层表里没有对应名称,只做存在性检查。
283
- - 层叠顺序由**导入时间**决定,与版本号无关:谁后导入谁在上。
284
- - `secureconfiguration` 经 Web API 读回恒为空,插件 secure config 只能人工确认。
285
- - 契约漂移读实时数据(不是快照),环境大时一次几十秒到几分钟。
286
-
287
- ---
288
-
289
- ## 开发
290
-
291
- ```
292
- index.js # Host 入口:注册 19 个工具、挂设置页路由
293
- client.js # 设置页(六个标签,无构建步骤)
294
- lib/
295
- client.js # Dataverse Web API 客户端(重试、分页、权限闸)
296
- auth.js # Entra ID 客户端凭据流 + 令牌缓存
297
- config.js # 配置加载与归一化
298
- resources.js # 19 类元数据资源的查询定义
299
- write-actions.js # 全部写操作的 planner / executor
300
- contract.js # 契约矩阵与漂移规则
301
- migrate.js # 迁移评估
302
- code-check.js # MR 检查(JS)
303
- csharp-check.js # MR 检查(C#)
304
- refs.js # 反向索引
305
- retention.js # 保留策略与磁盘清理
306
- ...
307
- ```
308
-
309
- 零运行时依赖:只用 Node 内置的 `fetch` / `fs` / `path`。改完用 `node --check` 逐个文件验证;Host 侧改动需要重载插件才会生效(`plugin_manager set_plugin enabled=false` 再 `true`),客户端代码需要刷新页面。
310
-
311
- 新增工具的约定:`parameters` 与 `output.schema` 都写标准 JSON Schema;返回「摘要 + 文件路径」,正文落文件;注册后加入 `index.js` 的 disposers。
312
-
313
- ---
314
-
315
- ## 状态
316
-
317
- 内部工具,按项目需要演进。版本语义:修 bug 升 patch,加工具/加能力升 minor,改配置结构升 major。
318
-
319
- 不随包提供环境配置与密钥;`d365.config.json` 与 `d365.secrets.json` 由每台机器自己填。
320
-
321
- ---
322
-
323
- ## 许可证
324
-
325
- [MIT](LICENSE) © 2026 iTanzhao
326
-
327
- 可以随意使用、修改、分发,保留版权声明即可。不提供担保,也不授予商标使用权。
1
+ # dsh-d365-kit(D365 工具箱)
2
+
3
+ **[English](README.md)** | 简体中文
4
+
5
+ Dynamics 365 CE / Dataverse 的**开发与部署助手**,作为 [DeepSeek Harness](https://github.com/deepseek-ai) 的 bundle 安装。
6
+ 它把一个真实的 D365 组织变成 agent 能直接查的东西:元数据、解决方案层、快照差异、引用关系、迁移风险、代码改动的影响面,以及受控的写入。
7
+
8
+ > 十九个工具、一个设置页。默认只读:勾选什么就只做什么,元数据也由「读取元数据」这一项控制(默认开启)。
9
+
10
+ ```
11
+ 你:DEV 的 account 上 contoso_customertier 这个字段,现在还有哪些表单和视图在用它?
12
+ agent:表单 17 张、视图 64 个(列 62 / 筛选 50)、业务流程 0 个 …
13
+ ```
14
+
15
+ ---
16
+
17
+ ## 它解决什么问题
18
+
19
+ D365 项目的日常摩擦,大多不是"不会写代码",而是**环境之间的信息不对称**:
20
+
21
+ | 问题 | 这个插件怎么答 |
22
+ | --- | --- |
23
+ | 这个解决方案发到 SIT,会不会把别的解决方案的定制压掉? | `d365_migrate` 逐组件查层,列出会被遮蔽的解决方案、缺失的组件、会丢的选项值 |
24
+ | 为什么两个环境的同一张表单不一样? | `d365_layers` 告诉你是谁覆盖了它,`d365_diff` 给出字段级差异 |
25
+ | 删这个字段会不会出事? | `d365_refs` 反查表单 / 视图 / 流程 / 插件步骤,`d365_data` 看还有多少条记录在用 |
26
+ | 这个 MR 发布到 UAT 能跑起来吗? | `d365_code_check` 把 JS 映射到 Web 资源与表单、把 C# 映射到程序集/类型/步骤/镜像 |
27
+ | 上游改了插件,下游跟上了吗? | `d365_contract` 把上游注册当契约,逐条比对下游,带豁免与趋势 |
28
+ | 现在能发布吗? | `d365_health` 看挂起的导入/发布与失败作业,写入前的预检查用的是同一份数据 |
29
+ | 补一个字段 / 选项值 / 视图列? | `d365_write` 生成计划 → 人在对话里确认 → 才写入,事后可查审计 |
30
+
31
+ ---
32
+
33
+ ## 功能一览
34
+
35
+ ### 连接与环境
36
+
37
+ | 工具 | 用途 |
38
+ | --- | --- |
39
+ | `d365_envs` | 环境清单、凭据是否齐全;`check: true` 时真实连一次 |
40
+ | `d365_configure` | 增删改环境(URL、租户、ClientId、密钥)、测连通性 |
41
+ | `d365_health` | 挂起/失败的后台作业、正在进行的导入发布、最近安装的解决方案 |
42
+
43
+ ### 元数据与解决方案层
44
+
45
+ | 工具 | 用途 |
46
+ | --- | --- |
47
+ | `d365_metadata` | 19 类资源:实体、字段、关系、表单、视图、工作流、业务规则、插件、Web 资源、解决方案、组件、Custom API、站点地图、选项集 |
48
+ | `d365_layers` | `msdyn_componentlayer`:某组件被哪些解决方案覆盖过、谁在最上层、当前生效的是哪一层 |
49
+
50
+ ### 快照与对比
51
+
52
+ | 工具 | 用途 |
53
+ | --- | --- |
54
+ | `d365_sync` | 把环境的元数据拉成本地快照,逐资源记录「完整 / 被截断 / 失败」 |
55
+ | `d365_diff` | 两份快照的字段级差异(新增、删除、修改),带噪声过滤与快照过期提示 |
56
+
57
+ ### 影响面与数据
58
+
59
+ | 工具 | 用途 |
60
+ | --- | --- |
61
+ | `d365_refs` | 反查:字段 → 表单/视图/流程;Web 资源 → 表单与事件;程序集 → 类型与步骤 |
62
+ | `d365_data` | 业务记录 count / group by / sample(需授权 `data.read`) |
63
+ | `d365_data_write` | 新建或修改一条业务记录,对话确认后执行(需 `data.write`) |
64
+ | `d365_data_sync` | 环境之间镜像记录(保持 GUID、解析 lookup、报告冲突),或按 id 清单批量改一个字段 |
65
+
66
+ ### 写入
67
+
68
+ | 工具 | 用途 |
69
+ | --- | --- |
70
+ | `d365_write` | 选项集增/改/删值、新增/改/删字段、改表显示名、增删系统视图列;`plan-*` 只出计划,`execute` 必须人工确认 |
71
+
72
+ ### 迁移与检查
73
+
74
+ | 工具 | 用途 |
75
+ | --- | --- |
76
+ | `d365_migrate` | 解决方案迁移风险评估:层遮蔽、组件缺失、选项值丢失、版本与受管状态 |
77
+ | `d365_contract` | 契约矩阵与漂移:程序集、插件类型、步骤、表单库、Handler、站点地图、选项值;带豁免与趋势 |
78
+ | `d365_code_check` | 读 GitLab MR,JS/C# 改动 → 目标环境核对,输出阻断 / 警告 / 人工确认 |
79
+
80
+ ### 排查
81
+
82
+ | 工具 | 用途 |
83
+ | --- | --- |
84
+ | `d365_trace` | 插件跟踪日志:谁跑了、抛了什么、按签名归并;messageblock 里的凭据会屏蔽(需 `data.read`) |
85
+ | `d365_invoke` | 真正调一次 Dataverse 消息,看状态码与响应体;GET function 需 `data.read`,POST action 需 `message.invoke` 且每次确认 |
86
+ | `d365_flows` | Power Automate 云流(`workflow` 表 `category = 5`):目录、单条流程的触发器/动作/连接器、哪些流程会碰某张表 |
87
+
88
+ ### 运维
89
+
90
+ | 工具 | 用途 |
91
+ | --- | --- |
92
+ | `d365_reports` | 本机产物与占用、按保留策略清理(默认预演)、压缩快照 |
93
+
94
+ ---
95
+
96
+ ## 设置页
97
+
98
+ DSH Web UI 的「设置 → D365 工具箱」,六个标签页:
99
+
100
+ | 标签 | 内容 |
101
+ | --- | --- |
102
+ | 环境 | 环境清单、测试连接、默认环境 |
103
+ | 权限 | 按环境勾选能力(读业务数据 / 写入类)、变更默认解决方案、复制到其它环境 |
104
+ | 计划 | 待确认的写入计划、最近的变更记录与发布结果(可重新发布) |
105
+ | 数据 | 每类产物的文件数 / 体积 / 保留策略,预演并清理,压缩快照 |
106
+ | GitLab | 仓库地址、默认项目、只读令牌(`read_api`) |
107
+ | 常规 | 快照保留份数、默认行数上限、请求超时 |
108
+
109
+ 界面语言跟随 DSH(中文 / English)。环境清单与 `d365_configure` 走同一份存储代码,界面和 agent 看到的一定一致。
110
+
111
+ ---
112
+
113
+ ## 安装
114
+
115
+ 前置:DSH 桌面版;机器能访问 `*.dynamics.com`;一个只读应用用户(ClientId + 密钥)。
116
+
117
+ ```bash
118
+ # 从 npm 安装(最短,可升级;包发布到 npm 或内网 registry 后可用)
119
+ plugin_manager install_bundle target="dsh-d365-kit@0.34.3"
120
+
121
+ # 从 Git 安装(不需要 registry,可钉 tag)
122
+ plugin_manager install_bundle target="git+https://<your-git>/<group>/dsh-d365-kit.git#v0.34.3"
123
+
124
+ # 或从本地目录安装(link,改代码立刻生效)
125
+ plugin_manager install_bundle target="D:\path\to\dsh-d365-kit"
126
+ ```
127
+
128
+ `dsh-d365-kit@<版本>` 是从 **npm registry** 解析的;只发到 GitHub 时,用第二条的 `git+https://` 形式装。`.github/workflows/publish.yml` 会在**每次推 `main` 且 `package.json` 里的版本还没上架时**发布到 npm —— 改版本号、推送,npm 就有了;没改版本号再推,任务绿着退出、什么都不做。`v*` tag 可选,只用来做一致性校验(必须等于 `package.json` 的版本)。
129
+
130
+ 发布需要下面两种凭据之一,两种都没配时工作流是空转的:
131
+
132
+ | 认证方式 | 要配什么 | 磁盘上的密钥 |
133
+ | --- | --- | --- |
134
+ | Trusted publishing(推荐) | 仓库变量 `NPM_TRUSTED_PUBLISHING = true`,再在 npmjs.com 上把 trusted publisher 指到本仓库和这个 workflow 文件 | 无 |
135
+ | Granular token | 仓库 secret `NPM_TOKEN`(要能发布必须勾「Bypass two-factor authentication」) | 一个你需要轮换的 token |
136
+
137
+ 优先用 trusted publishing:token 那条路正是会漏进日志和聊天记录的东西。
138
+
139
+ 装完**重启一次 DSH**,Web 客户端才会把设置页代码加载进模块图。
140
+
141
+ 然后:设置 → D365 工具箱 → 环境 → 添加环境(key、URL、租户、ClientId、密钥)→ 测试连接 → 保存。
142
+ 默认只读;要读业务记录,去「权限」勾「读取业务数据」。
143
+
144
+ 完整步骤、凭据解析顺序、升级与卸载见 [docs/installation.md](docs/zh/installation.md)。
145
+
146
+ ---
147
+
148
+ ## 典型用法
149
+
150
+ ### 1. 发布前评估一个解决方案
151
+
152
+ ```
153
+ 这个解决方案发到 SIT 和 UAT 有什么风险?
154
+
155
+ d365_migrate action=assess source=dev solution=ContosoBase targets=["sit","uat"]
156
+ ```
157
+
158
+ 报告回答:目标有没有这个解决方案、源版本是不是更高、每个组件的层会被谁压住(列出被遮蔽的解决方案)、选项集会不会丢值。落在 `.d365/reports/migration-*.md`。
159
+
160
+ ### 2. 这个字段能删吗
161
+
162
+ ```
163
+ account.contoso_customertier 还有谁在用?顺便看下还有多少条记录带着值。
164
+
165
+ d365_refs kind=field entity=account attribute=contoso_customertier
166
+ d365_data action=group entity=account field=contoso_customertier
167
+ ```
168
+
169
+ ### 3. 两个环境为什么不一样
170
+
171
+ ```
172
+ d365_sync environments=["dev","sit"]
173
+ d365_diff base=dev head=sit resources=["forms","views","attributes"]
174
+ d365_layers component=Account componentType=SystemForm
175
+ ```
176
+
177
+ ### 4. 检查一个 MR 能不能发到 UAT
178
+
179
+ ```
180
+ d365_code_check mergeRequest="https://gitlab.example.com/contoso/powerapps/-/merge_requests/7759/diffs" targets=["uat"]
181
+ ```
182
+
183
+ JS 改动会映射到 Web 资源与表单,检查读取的字段是否在表单上、删除的函数是否仍被 Handler 引用;
184
+ C# 改动会核对程序集版本、插件类型、步骤、step 镜像与过滤属性。静态判不了的进「人工确认」清单。
185
+
186
+ ### 5. 补 36 个税号选项(写入全流程)
187
+
188
+ ```
189
+ d365_write action=plan-add-options environment=dev optionSet=contoso_taxcategoryos labels=["AD3|Andorra: Tax Register Number", ...]
190
+
191
+ (agent 返回计划与操作列表)
192
+ 执行 mw04aul6-1ci6aa
193
+ ```
194
+
195
+ 第二步会在对话里弹确认卡片,点「批准执行」才写入;写入后只发布受影响的那个选项集,不重算整个组织。
196
+
197
+ ### 6. 上游插件改了,下游还缺什么
198
+
199
+ ```
200
+ d365_contract action=drift source=dev targets=["sit","uat"] forms=true
201
+ ```
202
+
203
+ 更多可直接复制的说法见 [examples/prompts.md](examples/prompts.zh-CN.md) 与 [docs/scenarios.md](docs/zh/scenarios.md)。
204
+
205
+ ---
206
+
207
+ ## 权限模型
208
+
209
+ 默认**只读**。能力按环境授权,存在 `d365.config.json` 的 `write.environments`;设置页里每个环境单独一块,用分隔线隔开:
210
+
211
+ ```json
212
+ {
213
+ "write": {
214
+ "capabilityVersion": 2,
215
+ "environments": {
216
+ "dev": ["metadata.read", "data.read", "optionValue.add", "attribute.add"],
217
+ "sit": ["metadata.read", "data.read"]
218
+ },
219
+ "solutionUniqueName": "ContosoBase"
220
+ }
221
+ }
222
+ ```
223
+
224
+ 环境没有条目 = 还没配过,默认只开 `metadata.read`;条目是空数组 = 全关。
225
+
226
+ | 能力 | 对应操作 | 作用 |
227
+ | --- | --- | --- |
228
+ | `metadata.read` | 元数据 `GET` | 读表 / 字段 / 表单 / 视图 / 插件 / 层(默认开启) |
229
+ | `data.read` | 业务数据 `GET` | 读业务记录;不授权时读不到表里的记录 |
230
+ | `data.write` | `POST` / `PATCH` | 新建或修改业务记录(不含删除) |
231
+ | `optionValue.add` | `InsertOptionValue` | 新增选项值(全局或字段本地) |
232
+ | `optionValue.updateLabel` | `UpdateOptionValue` | 改选项标签 |
233
+ | `optionValue.delete` | `DeleteOptionValue` | 永久删除选项值(高危) |
234
+ | `attribute.add` | `CreateAttribute` | 新增字段 |
235
+ | `attribute.update` | `UpdateAttribute` | 改字段显示名 / 描述 / 必填级别 |
236
+ | `attribute.delete` | `DeleteAttribute` | 永久删除字段及其数据(高危) |
237
+ | `entity.update` | `UpdateEntity` | 改表显示名与描述 |
238
+ | `view.columns` | `UpdateSavedQuery` | 增删系统视图的列 |
239
+ | `layer.remove` | `RemoveActiveCustomizations` | 移除组件最上面的未受管自定义层(高危) |
240
+
241
+ 写入是两步:`plan-*` 只读生成计划 → 人在对话(或设置页)确认后 `execute`。执行前会查环境是否正在导入/发布,忙则拒绝;每次执行逐条记进 `.d365/changes/`,计划有 `pending → running → done/failed` 状态,重跑不会重复提交。
242
+
243
+ 判定收在 `lib/client.js` 一处:先看是不是元数据请求(要 `metadata.read`),其余 `GET` 一律按业务数据拦截(要 `data.read`),非 `GET` 的写还要 `data.write`。拦截发生在取令牌之前,新增工具绕不过这三道闸。
244
+
245
+ 详见 [docs/permissions.md](docs/zh/permissions.md)。
246
+
247
+ ---
248
+
249
+ ## 本地产物
250
+
251
+ ```
252
+ <工作区>/
253
+ d365.config.json # 环境清单与工具参数(可进 Git)
254
+ d365.secrets.json # 客户端密钥(明文,别提交)
255
+ .d365/
256
+ snapshots/<env>/<id>/ # 元数据快照 + manifest
257
+ diffs/ # 对比报告
258
+ reports/ # 迁移、契约、代码检查、历史趋势
259
+ query/ # 查询留证、数据写入审计
260
+ pending-writes/ # 待确认计划
261
+ changes/ # 已执行的变更与发布结果
262
+ waivers.json # 契约豁免
263
+ ```
264
+
265
+ `.d365/` 自带 `.gitignore`(内容 `*`)。保留策略默认:快照 2 份/30 天、报告 50/90、diff 20/30、query 100/7、changes 200/180,写产物后自动清理,`waivers.json` 与待确认计划永不清理。
266
+
267
+ ---
268
+
269
+ ## 文档
270
+
271
+ | 文档 | 内容 |
272
+ | --- | --- |
273
+ | [docs/installation.md](docs/zh/installation.md) | 安装、首次配置、凭据、升级、卸载 |
274
+ | [docs/tools.md](docs/zh/tools.md) | 19 个工具的参数、返回与示例 |
275
+ | [docs/scenarios.md](docs/zh/scenarios.md) | 8 个真实场景的完整走法 |
276
+ | [docs/permissions.md](docs/zh/permissions.md) | 能力表、写入流程、预检查、安全边界 |
277
+ | [docs/checks.md](docs/zh/checks.md) | 迁移评估、契约漂移、代码检查的规则与置信度 |
278
+ | [docs/troubleshooting.md](docs/zh/troubleshooting.md) | 常见错误码与排查 |
279
+ | [skills/d365-troubleshooting/SKILL.md](skills/d365-troubleshooting/SKILL.md) | Agent skill:从跟踪日志到复现调用的排查流程(插件自己注册,不用复制) |
280
+ | [docs/architecture.md](docs/zh/architecture.md) | 模块结构、数据流、如何加一个工具 |
281
+ | [CHANGELOG.md](CHANGELOG.zh-CN.md) | 版本记录 |
282
+
283
+ ---
284
+
285
+ ## 已知边界
286
+
287
+ - 不采 Ribbon 与 Power Automate 云流。
288
+ - `attributes` 按实体逐个请求,实体多时请求量等于实体数;用 `entities` 缩小范围。
289
+ - 元数据表基本没有增量游标,每次同步都是全量;增量只能「跑第二次然后 diff」。
290
+ - `d365_layers` 依赖 `msdyn_componentlayer` 虚拟表:必须同时给组件 id 与类型,只给名字返回 0 行。
291
+ - 组件类型 36 / 50 / 70(报表、图表类)在层表里没有对应名称,只做存在性检查。
292
+ - 层叠顺序由**导入时间**决定,与版本号无关:谁后导入谁在上。
293
+ - `secureconfiguration` 经 Web API 读回恒为空,插件 secure config 只能人工确认。
294
+ - 契约漂移读实时数据(不是快照),环境大时一次几十秒到几分钟。
295
+
296
+ ---
297
+
298
+ ## 开发
299
+
300
+ ```
301
+ index.js # Host 入口:注册 19 个工具、挂设置页路由
302
+ client.js # 设置页(六个标签,无构建步骤)
303
+ lib/
304
+ client.js # Dataverse Web API 客户端(重试、分页、权限闸)
305
+ auth.js # Entra ID 客户端凭据流 + 令牌缓存
306
+ config.js # 配置加载与归一化
307
+ resources.js # 19 类元数据资源的查询定义
308
+ write-actions.js # 全部写操作的 planner / executor
309
+ contract.js # 契约矩阵与漂移规则
310
+ migrate.js # 迁移评估
311
+ code-check.js # MR 检查(JS)
312
+ csharp-check.js # MR 检查(C#)
313
+ refs.js # 反向索引
314
+ retention.js # 保留策略与磁盘清理
315
+ ...
316
+ ```
317
+
318
+ 零运行时依赖:只用 Node 内置的 `fetch` / `fs` / `path`。改完用 `node --check` 逐个文件验证;Host 侧改动需要重载插件才会生效(`plugin_manager set_plugin enabled=false` 再 `true`),客户端代码需要刷新页面。
319
+
320
+ 新增工具的约定:`parameters` 与 `output.schema` 都写标准 JSON Schema;返回「摘要 + 文件路径」,正文落文件;注册后加入 `index.js` 的 disposers。
321
+
322
+ ---
323
+
324
+ ## 状态
325
+
326
+ 内部工具,按项目需要演进。版本语义:修 bug 升 patch,加工具/加能力升 minor,改配置结构升 major。
327
+
328
+ 不随包提供环境配置与密钥;`d365.config.json` 与 `d365.secrets.json` 由每台机器自己填。
329
+
330
+ ---
331
+
332
+ ## 许可证
333
+
334
+ [MIT](LICENSE) © 2026 iTanzhao
335
+
336
+ 可以随意使用、修改、分发,保留版权声明即可。不提供担保,也不授予商标使用权。