@microi.net/cli 4.7.4 → 4.7.6

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.
@@ -1,13 +1,13 @@
1
1
  {
2
- "builtAt": "2026-08-07T04:21:56.206Z",
2
+ "builtAt": "2026-08-07T13:44:29.671Z",
3
3
  "source": "../microi.skills",
4
4
  "extension": {
5
5
  "name": "v8-engine",
6
- "version": "4.7.4",
6
+ "version": "4.7.6",
7
7
  "publisher": "Microi"
8
8
  },
9
9
  "skills": {
10
- "version": "4.7.4",
10
+ "version": "4.7.6",
11
11
  "versionRule": "Microi version uses three numeric parts. Each publish increments the last part; when a part exceeds 9 it carries to the previous part: 1.0.9 -> 1.1.0, 1.9.9 -> 2.0.0.",
12
12
  "managedBy": "Microi.VSCode/bump-version.js"
13
13
  },
@@ -15,14 +15,14 @@
15
15
  "dir": "dist/microi.skills",
16
16
  "files": 105,
17
17
  "skills": 58,
18
- "bytes": 1630404
18
+ "bytes": 1635633
19
19
  },
20
20
  "fileHashes": {
21
- ".microi-skills-version.json": "fb7f2280ee7f2d9001407d57fd7c3788ab5c128f2ae42c7dd8d2d3e10456deea",
21
+ ".microi-skills-version.json": "295fdb3f705012300778f392f0459f16605bb33804aa3b520a1c672bd23f1db6",
22
22
  "README.md": "f88db8f5a0ad3788583b1a0787cb4c485f1027e50a5c21997da41334e2be3b82",
23
23
  "ai-engine/SKILL.md": "371b00ce9860d1516f6eb7eeaed001cbfa852c52e7c0cfccbedc4a71a113e568",
24
24
  "ai-engine/agents/openai.yaml": "40deb07801006a46b9a7f0020d13251955eeadd04c8e591160210479936f8b5b",
25
- "app-store/SKILL.md": "ce238cf6860256fcfd5eba8ae52a03320ffca9137d57504f27f64e6d9f6ac3dd",
25
+ "app-store/SKILL.md": "372243a3e8a9ed5163ca458e15eb1211474aef327ac553202884bfbb0321722a",
26
26
  "app-store/agents/openai.yaml": "eda8f5cf043e7b8fb0e4fb3acf0625fef95eb49586b43187ced277cd0ae4a2c4",
27
27
  "business-blueprint/SKILL.md": "ea379a85476d262f4fc72a5846a06354893065052ef64370bbc7e3a2753a498d",
28
28
  "datasource-engine/SKILL.md": "bfd0cab8318eef375ca49f27c0511fce7e939a1c795678e83cf2d3438e24915f",
@@ -50,7 +50,7 @@
50
50
  "microi-deployment/SKILL.md": "26faa91740c874cfd676ceb69c1e4f8c12acfb85a2fc9fe1e8d0298ffe84b310",
51
51
  "microi-deployment/references/deployment-matrix.md": "32d9d1424bf19eae0d2cee2b1667203c830ea7610c71a806e7ddf785a0083009",
52
52
  "microi-docs-coverage/SKILL.md": "5fad3dd7b83cf01ef7a303506902c95da7ae85d60b0067d266f1e2fa2326db95",
53
- "microi-docs-coverage/references/capability-map.md": "f460427304dca6f4d3ff57b79eaa3c5eab72b03726655b0c8bac1e27c844ce9b",
53
+ "microi-docs-coverage/references/capability-map.md": "04822bf99eb1732c6bffe87eae14869e5eca11e0bf967048bdc402a865a5a0a8",
54
54
  "microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs": "ebd57f17f2ebae499bfa59ad17830db458590feb76f7f0f20219ff0987b33af3",
55
55
  "microi-form-engine/SKILL.md": "1afefedb468b5bab219f726bddb9ceca99547ee4149722a847a50eb9001b6927",
56
56
  "microi-form-engine/references/component-catalog.md": "68963c2d5211a4610c09fab1fa127a349339abbb7427509b183d4be72e977c7b",
@@ -67,7 +67,7 @@
67
67
  "microi-system-delivery/SKILL.md": "74afccf9e01c29a72f1f0bbd8a654875b53e10188d98cb6f0d65cf0055ff4d7f",
68
68
  "microi-ui/SKILL.md": "606a9cfc2e9cbcb41e9e26ef9c09bb2ca31c4edc24af00058aa059b54a01f2fe",
69
69
  "microi-uniapp-frontend/SKILL.md": "d031dca0ed4182954e383e9828263d46414330f0a014487867b628f655b5bb26",
70
- "microi.v8.js": "bc886f196fc4dc9604a5edc89afd59a75a64dcb36066fc0ca7f07879d5870732",
70
+ "microi.v8.js": "25ff9e9aca3ff5167a1f3f06e262e3389a6d732cb12b9a3ddb4f218fb331ef53",
71
71
  "module-engine/SKILL.md": "ee19f0b8f7f960a274236c93cb9639c216004efdc9ea529df39e3ab5645ae340",
72
72
  "module-engine/references/module-config.md": "99664bde53029bc3342bff8de820aab56ee94898df7dbc31f054e911871c46dc",
73
73
  "ocr-engine/SKILL.md": "16f7ee8d3485f47d2cb524f0c3fdea609f7de5581ba46da9f34d32772422c050",
@@ -112,124 +112,124 @@
112
112
  "v8-menu-buttons/SKILL.md": "fc933bf7685db029517f05df5e75560118ceb90a4a9d52922f046d34334a3082",
113
113
  "v8-mongodb/SKILL.md": "7da703b5dc9fb9613cca1929fd854e3d333ad7d86200b839bb78ccdc8e0cc6cf",
114
114
  "v8-mq-mqtt/SKILL.md": "3894fc353a3e9896b16b54b9e12758f0aea950968f80b7f3ec86c6652040341c",
115
- "v8-saas-multi-tenant/SKILL.md": "0145ddd39e109e39b601cfac45b746624f21d9dfce5951b662ac713e80f3fc72",
116
- "v8-security/SKILL.md": "91ccb35136fce4e5c9524b9a787ca33712fac06be9c114a925e48f9b5be1e62c",
115
+ "v8-saas-multi-tenant/SKILL.md": "92663c00834d0070e145a84da15519d1d5c6aa77d733df09b51bdd221a262bdf",
116
+ "v8-security/SKILL.md": "8906f239cfafd13d4e3bb4d98b6f0914a7aca8470ffdb32398d06fa53f7b0690",
117
117
  "v8-sql-query/SKILL.md": "0ebedf72732479e24ca7528120345d468f98fbf96c21a8f45aaa64eb8ef6a488",
118
118
  "v8-table-event/SKILL.md": "ddeb3020e8c7e3002c8f8598a65208b7a2f706ee13f040037f85979c7bc1e8fd",
119
119
  "v8-template-engine/SKILL.md": "20002c2124214641b782db9deabb367c151b6be1b2d32f6689c163dcb0925cce",
120
120
  "v8-utilities/SKILL.md": "cdc1c33e2c464a89635bbcb96bf5079d9e22c58a0c70158634c2ab70fd034d3b",
121
- "v8-utilities/references/client-api-index.md": "88741d5f5bb2b727c72ae553819cdccd647862414bf03f973ecacf79f9454296",
121
+ "v8-utilities/references/client-api-index.md": "9b6cc82f1e1d40963354d120d838ebe003b1125e9e479c6f79fa5866e3c21bd8",
122
122
  "v8-utilities/references/platform-http-routes.md": "87579eef4e89b4c80e1757ad34ec951e0ccadb6bd15aab4f3ab247f55d5f1cd5",
123
- "v8-utilities/references/server-api-index.md": "8879c16421fccbf69177683ef201976292e7b84757f53bcf0945bad985426893",
123
+ "v8-utilities/references/server-api-index.md": "72655af1078b0c63ace253f6a6ab74847abffe38829fdcb55780861d8d4b0e9f",
124
124
  "v8-workflow/SKILL.md": "cd6738edd79f628948adfac898b6d58a81feb28d1ec6d1f83fc12758fb570819",
125
- "workspace-conventions/SKILL.md": "950480ad1e5a32176823d4f024af6aecd9b37ee7423c05e2ec4c1b1a4130cb66"
125
+ "workspace-conventions/SKILL.md": "1fb73d6ebfa6683d708d47cbc772505bbb2a9e90d9c7afad23007a166bd8cae5"
126
126
  },
127
127
  "fileVersions": {
128
- ".microi-skills-version.json": "4.7.4",
129
- "README.md": "4.7.4",
130
- "ai-engine/SKILL.md": "4.7.4",
131
- "ai-engine/agents/openai.yaml": "4.7.4",
132
- "app-store/SKILL.md": "4.7.4",
133
- "app-store/agents/openai.yaml": "4.7.4",
134
- "business-blueprint/SKILL.md": "4.7.4",
135
- "datasource-engine/SKILL.md": "4.7.4",
136
- "datasource-engine/agents/openai.yaml": "4.7.4",
137
- "dos-orm/SKILL.md": "4.7.4",
138
- "dos-orm/references/api-reference.md": "4.7.4",
139
- "job-engine/SKILL.md": "4.7.4",
140
- "job-engine/agents/openai.yaml": "4.7.4",
141
- "message-notification/SKILL.md": "4.7.4",
142
- "message-notification/agents/openai.yaml": "4.7.4",
143
- "message-notification/references/contracts.md": "4.7.4",
144
- "microi-ai-app-auth.js": "4.7.4",
145
- "microi-ai-application/SKILL.md": "4.7.4",
146
- "microi-ai-application/agents/openai.yaml": "4.7.4",
147
- "microi-ai-application/references/frontend-baseline.md": "4.7.4",
148
- "microi-client-frontend/SKILL.md": "4.7.4",
149
- "microi-datasource-mapping/SKILL.md": "4.7.4",
150
- "microi-db-schema/SKILL.md": "4.7.4",
151
- "microi-db-schema/agents/openai.yaml": "4.7.4",
152
- "microi-db-schema/references/core-tables.md": "4.7.4",
153
- "microi-db-schema/references/form-component-options.md": "4.7.4",
154
- "microi-db-schema/references/schema-overview.md": "4.7.4",
155
- "microi-db-schema/references/schema.md": "4.7.4",
156
- "microi-db-schema/references/table-catalog.md": "4.7.4",
157
- "microi-deployment/SKILL.md": "4.7.4",
158
- "microi-deployment/references/deployment-matrix.md": "4.7.4",
159
- "microi-docs-coverage/SKILL.md": "4.7.4",
160
- "microi-docs-coverage/references/capability-map.md": "4.7.4",
161
- "microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs": "4.7.4",
162
- "microi-form-engine/SKILL.md": "4.7.4",
163
- "microi-form-engine/references/component-catalog.md": "4.7.4",
164
- "microi-form-engine/references/data-source-events.md": "4.7.4",
165
- "microi-form-layout/SKILL.md": "4.7.4",
166
- "microi-frontend-sdk/SKILL.md": "4.7.4",
167
- "microi-left-right-layout/SKILL.md": "4.7.4",
168
- "microi-microservice/SKILL.md": "4.7.4",
169
- "microi-microservice/references/runtime-delivery.md": "4.7.4",
170
- "microi-mobile-app-quality/SKILL.md": "4.7.4",
171
- "microi-solution-quotation/SKILL.md": "4.7.4",
172
- "microi-solution-quotation/agents/openai.yaml": "4.7.4",
173
- "microi-solution-quotation/scripts/build_solution_quote.py": "4.7.4",
174
- "microi-system-delivery/SKILL.md": "4.7.4",
175
- "microi-ui/SKILL.md": "4.7.4",
176
- "microi-uniapp-frontend/SKILL.md": "4.7.4",
177
- "microi.v8.js": "4.7.4",
178
- "module-engine/SKILL.md": "4.7.4",
179
- "module-engine/references/module-config.md": "4.7.4",
180
- "ocr-engine/SKILL.md": "4.7.4",
181
- "ocr-engine/agents/openai.yaml": "4.7.4",
182
- "page-engine/SKILL.md": "4.7.4",
183
- "performance-testing/SKILL.md": "4.7.4",
184
- "playwright-e2e/SKILL.md": "4.7.4",
185
- "print-engine/SKILL.md": "4.7.4",
186
- "production-readonly-audit/SKILL.md": "4.7.4",
187
- "report-engine/SKILL.md": "4.7.4",
188
- "report-engine/agents/openai.yaml": "4.7.4",
189
- "search-engine/SKILL.md": "4.7.4",
190
- "search-engine/agents/openai.yaml": "4.7.4",
191
- "spider-engine/SKILL.md": "4.7.4",
192
- "translate-engine/SKILL.md": "4.7.4",
193
- "translate-engine/agents/openai.yaml": "4.7.4",
194
- "ui-design/SKILL.md": "4.7.4",
195
- "ui-design/assets/pattern-showcase/app.js": "4.7.4",
196
- "ui-design/assets/pattern-showcase/index.html": "4.7.4",
197
- "ui-design/assets/pattern-showcase/styles.css": "4.7.4",
198
- "ui-design/assets/templates/MCI-DESIGN.md": "4.7.4",
199
- "ui-design/references/design-pattern-library.md": "4.7.4",
200
- "ui-design/references/mci-design-contract.md": "4.7.4",
201
- "ui-design/references/motion-and-media.md": "4.7.4",
202
- "ui-design/references/product-flow-recipes.md": "4.7.4",
203
- "uniapp-mall-assets/SKILL.md": "4.7.4",
204
- "v8-api-config/SKILL.md": "4.7.4",
205
- "v8-cache-pattern/SKILL.md": "4.7.4",
206
- "v8-crud-api/SKILL.md": "4.7.4",
207
- "v8-debugging/SKILL.md": "4.7.4",
208
- "v8-explorer-tree/SKILL.md": "4.7.4",
209
- "v8-export-import/SKILL.md": "4.7.4",
210
- "v8-file-upload/SKILL.md": "4.7.4",
211
- "v8-formengine-http/SKILL.md": "4.7.4",
212
- "v8-frontend-events/SKILL.md": "4.7.4",
213
- "v8-frontend-events/references/bluetooth-print-api.md": "4.7.4",
214
- "v8-frontend-events/references/bluetooth-print.md": "4.7.4",
215
- "v8-http-integration/SKILL.md": "4.7.4",
216
- "v8-image-processing/SKILL.md": "4.7.4",
217
- "v8-image-processing/agents/openai.yaml": "4.7.4",
218
- "v8-image-processing/references/api-reference.md": "4.7.4",
219
- "v8-menu-buttons/SKILL.md": "4.7.4",
220
- "v8-mongodb/SKILL.md": "4.7.4",
221
- "v8-mq-mqtt/SKILL.md": "4.7.4",
222
- "v8-saas-multi-tenant/SKILL.md": "4.7.4",
223
- "v8-security/SKILL.md": "4.7.4",
224
- "v8-sql-query/SKILL.md": "4.7.4",
225
- "v8-table-event/SKILL.md": "4.7.4",
226
- "v8-template-engine/SKILL.md": "4.7.4",
227
- "v8-utilities/SKILL.md": "4.7.4",
228
- "v8-utilities/references/client-api-index.md": "4.7.4",
229
- "v8-utilities/references/platform-http-routes.md": "4.7.4",
230
- "v8-utilities/references/server-api-index.md": "4.7.4",
231
- "v8-workflow/SKILL.md": "4.7.4",
232
- "workspace-conventions/SKILL.md": "4.7.4"
128
+ ".microi-skills-version.json": "4.7.6",
129
+ "README.md": "4.7.6",
130
+ "ai-engine/SKILL.md": "4.7.6",
131
+ "ai-engine/agents/openai.yaml": "4.7.6",
132
+ "app-store/SKILL.md": "4.7.6",
133
+ "app-store/agents/openai.yaml": "4.7.6",
134
+ "business-blueprint/SKILL.md": "4.7.6",
135
+ "datasource-engine/SKILL.md": "4.7.6",
136
+ "datasource-engine/agents/openai.yaml": "4.7.6",
137
+ "dos-orm/SKILL.md": "4.7.6",
138
+ "dos-orm/references/api-reference.md": "4.7.6",
139
+ "job-engine/SKILL.md": "4.7.6",
140
+ "job-engine/agents/openai.yaml": "4.7.6",
141
+ "message-notification/SKILL.md": "4.7.6",
142
+ "message-notification/agents/openai.yaml": "4.7.6",
143
+ "message-notification/references/contracts.md": "4.7.6",
144
+ "microi-ai-app-auth.js": "4.7.6",
145
+ "microi-ai-application/SKILL.md": "4.7.6",
146
+ "microi-ai-application/agents/openai.yaml": "4.7.6",
147
+ "microi-ai-application/references/frontend-baseline.md": "4.7.6",
148
+ "microi-client-frontend/SKILL.md": "4.7.6",
149
+ "microi-datasource-mapping/SKILL.md": "4.7.6",
150
+ "microi-db-schema/SKILL.md": "4.7.6",
151
+ "microi-db-schema/agents/openai.yaml": "4.7.6",
152
+ "microi-db-schema/references/core-tables.md": "4.7.6",
153
+ "microi-db-schema/references/form-component-options.md": "4.7.6",
154
+ "microi-db-schema/references/schema-overview.md": "4.7.6",
155
+ "microi-db-schema/references/schema.md": "4.7.6",
156
+ "microi-db-schema/references/table-catalog.md": "4.7.6",
157
+ "microi-deployment/SKILL.md": "4.7.6",
158
+ "microi-deployment/references/deployment-matrix.md": "4.7.6",
159
+ "microi-docs-coverage/SKILL.md": "4.7.6",
160
+ "microi-docs-coverage/references/capability-map.md": "4.7.6",
161
+ "microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs": "4.7.6",
162
+ "microi-form-engine/SKILL.md": "4.7.6",
163
+ "microi-form-engine/references/component-catalog.md": "4.7.6",
164
+ "microi-form-engine/references/data-source-events.md": "4.7.6",
165
+ "microi-form-layout/SKILL.md": "4.7.6",
166
+ "microi-frontend-sdk/SKILL.md": "4.7.6",
167
+ "microi-left-right-layout/SKILL.md": "4.7.6",
168
+ "microi-microservice/SKILL.md": "4.7.6",
169
+ "microi-microservice/references/runtime-delivery.md": "4.7.6",
170
+ "microi-mobile-app-quality/SKILL.md": "4.7.6",
171
+ "microi-solution-quotation/SKILL.md": "4.7.6",
172
+ "microi-solution-quotation/agents/openai.yaml": "4.7.6",
173
+ "microi-solution-quotation/scripts/build_solution_quote.py": "4.7.6",
174
+ "microi-system-delivery/SKILL.md": "4.7.6",
175
+ "microi-ui/SKILL.md": "4.7.6",
176
+ "microi-uniapp-frontend/SKILL.md": "4.7.6",
177
+ "microi.v8.js": "4.7.6",
178
+ "module-engine/SKILL.md": "4.7.6",
179
+ "module-engine/references/module-config.md": "4.7.6",
180
+ "ocr-engine/SKILL.md": "4.7.6",
181
+ "ocr-engine/agents/openai.yaml": "4.7.6",
182
+ "page-engine/SKILL.md": "4.7.6",
183
+ "performance-testing/SKILL.md": "4.7.6",
184
+ "playwright-e2e/SKILL.md": "4.7.6",
185
+ "print-engine/SKILL.md": "4.7.6",
186
+ "production-readonly-audit/SKILL.md": "4.7.6",
187
+ "report-engine/SKILL.md": "4.7.6",
188
+ "report-engine/agents/openai.yaml": "4.7.6",
189
+ "search-engine/SKILL.md": "4.7.6",
190
+ "search-engine/agents/openai.yaml": "4.7.6",
191
+ "spider-engine/SKILL.md": "4.7.6",
192
+ "translate-engine/SKILL.md": "4.7.6",
193
+ "translate-engine/agents/openai.yaml": "4.7.6",
194
+ "ui-design/SKILL.md": "4.7.6",
195
+ "ui-design/assets/pattern-showcase/app.js": "4.7.6",
196
+ "ui-design/assets/pattern-showcase/index.html": "4.7.6",
197
+ "ui-design/assets/pattern-showcase/styles.css": "4.7.6",
198
+ "ui-design/assets/templates/MCI-DESIGN.md": "4.7.6",
199
+ "ui-design/references/design-pattern-library.md": "4.7.6",
200
+ "ui-design/references/mci-design-contract.md": "4.7.6",
201
+ "ui-design/references/motion-and-media.md": "4.7.6",
202
+ "ui-design/references/product-flow-recipes.md": "4.7.6",
203
+ "uniapp-mall-assets/SKILL.md": "4.7.6",
204
+ "v8-api-config/SKILL.md": "4.7.6",
205
+ "v8-cache-pattern/SKILL.md": "4.7.6",
206
+ "v8-crud-api/SKILL.md": "4.7.6",
207
+ "v8-debugging/SKILL.md": "4.7.6",
208
+ "v8-explorer-tree/SKILL.md": "4.7.6",
209
+ "v8-export-import/SKILL.md": "4.7.6",
210
+ "v8-file-upload/SKILL.md": "4.7.6",
211
+ "v8-formengine-http/SKILL.md": "4.7.6",
212
+ "v8-frontend-events/SKILL.md": "4.7.6",
213
+ "v8-frontend-events/references/bluetooth-print-api.md": "4.7.6",
214
+ "v8-frontend-events/references/bluetooth-print.md": "4.7.6",
215
+ "v8-http-integration/SKILL.md": "4.7.6",
216
+ "v8-image-processing/SKILL.md": "4.7.6",
217
+ "v8-image-processing/agents/openai.yaml": "4.7.6",
218
+ "v8-image-processing/references/api-reference.md": "4.7.6",
219
+ "v8-menu-buttons/SKILL.md": "4.7.6",
220
+ "v8-mongodb/SKILL.md": "4.7.6",
221
+ "v8-mq-mqtt/SKILL.md": "4.7.6",
222
+ "v8-saas-multi-tenant/SKILL.md": "4.7.6",
223
+ "v8-security/SKILL.md": "4.7.6",
224
+ "v8-sql-query/SKILL.md": "4.7.6",
225
+ "v8-table-event/SKILL.md": "4.7.6",
226
+ "v8-template-engine/SKILL.md": "4.7.6",
227
+ "v8-utilities/SKILL.md": "4.7.6",
228
+ "v8-utilities/references/client-api-index.md": "4.7.6",
229
+ "v8-utilities/references/platform-http-routes.md": "4.7.6",
230
+ "v8-utilities/references/server-api-index.md": "4.7.6",
231
+ "v8-workflow/SKILL.md": "4.7.6",
232
+ "workspace-conventions/SKILL.md": "4.7.6"
233
233
  },
234
234
  "files": [
235
235
  ".microi-skills-version.json",
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "4.7.4",
2
+ "version": "4.7.6",
3
3
  "versionRule": "Microi version uses three numeric parts. Each publish increments the last part; when a part exceeds 9 it carries to the previous part: 1.0.9 -> 1.1.0, 1.9.9 -> 2.0.0.",
4
4
  "managedBy": "Microi.VSCode/bump-version.js",
5
- "updatedAt": "2026-08-07T04:21:46.680Z"
5
+ "updatedAt": "2026-08-07T13:44:17.179Z"
6
6
  }
@@ -56,6 +56,7 @@ description: Microi 应用商城开发、打包、安装和升级规范。用于
56
56
  - 按钮调用后台安装接口时,前端只传应用/版本/安装 Id;目标租户和管理员身份由 Token 确定。
57
57
  - 每次安装、更新、重新安装生成稳定 `OperationId`。官方计数服务用共享数据库事件表唯一约束去重,并在同一事务内登记事件和递增 `InstallCount`;重试、跨节点和响应丢失不得重复计数。
58
58
  - “全部安装/更新”固定只处理 `ApplicationType=Platform` 的官方平台应用中未安装与存在新版本的项目,不得把 UniApp、Web、MicroService 或其它社区/AI 应用整库安装;已是最新版的应用不重新安装。批量计划、子项状态、checkpoint 和进度必须持久化到共享数据库/后台任务,支持多节点抢占、失败重试和重启恢复,不能依赖进程内集合或浏览器状态。
59
+ - 必须随所有后端版本自动落地的平台基础能力,仍要封装成受信任的官方 Platform 应用包,再由升级器调用统一 `import-microi-store-package` 幂等导入;禁止把表、字段、页面或微服务复制成定制 C# 迁移。身份验证、登录方式、个人中心与租户系统设置使用 `app.microi.saas-engine.json`:携带 `mci_system_setting`、`mci_user_external_identity`、默认设置和 `microi-platform-service`。默认行必须使用 `InsertIfMissing + ConfigKey`,只补缺失,不覆盖 `ValueSource=Tenant` 的租户值或租户后来明确关闭的功能。
59
60
  - 批量任务已经以“一个应用”为外层持久化恢复单元。规模可控的小型官方包应在一个事务中完成,避免对同一包体按 8 个字段反复下载、解析和重新排队;超过字段、表、DDL、流程、随包数据或资产安全阈值的大包继续使用内部 checkpoint 分片。热更新发现旧版批量计划不含 `ApplicationType` 时,必须丢弃旧计划并重新盘点,不能继续安装历史计划中的社区应用。
60
61
  - MySQL 宽表触发 65,535 字节行内上限时,只允许把不参与索引的 `varchar` 配置列无损提升为 `mediumtext`,并把类型覆盖持久化到后台任务 checkpoint;索引列和非行宽错误必须失败关闭。发布包对长连接串、密钥、回调地址、域名/白名单等字段应直接使用 `mediumtext`,同时更新 `DiyFields` 与建表 DDL,不能长期依赖安装时猜测。
61
62
  - 卸载是破坏性操作,必须明确列出将删除/保留的资源、二次确认并优先软删除/归档业务数据。
@@ -26,7 +26,7 @@ Markdown。第一列是相对 `microi.doc/docs/doc/` 的路径;第二列 Skill
26
26
  | `more/dos-orm.md` | dos-orm, v8-sql-query | ORM 查询、参数和事务 |
27
27
  | `more/dos-result.md` | v8-utilities, v8-crud-api | DosResult/DosResultList 返回协议 |
28
28
  | `more/hdfs.md` | v8-file-upload | 分布式文件存储和 URL |
29
- | `more/identity-verification.md` | v8-security, v8-utilities, microi-microservice | DiyToken、Passkey、严格人脸、一次性步进票据和个人设置 |
29
+ | `more/identity-verification.md` | v8-security, v8-utilities, microi-microservice, app-store, v8-saas-multi-tenant | DiyToken、登录方式气泡、PasskeyAuthenticator TOTP、Gitee/微信/GitHub、动态租户设置、严格人脸、一次性步进票据、个人中心和自动升级包 |
30
30
  | `more/office.md` | v8-export-import, microi-microservice | Office 导入导出与在线编辑集成 |
31
31
  | `more/security.md` | v8-security | 平台安全和兼容基线 |
32
32
  | `more/sys-config.md` | v8-utilities, microi-deployment | 系统/租户配置和敏感边界 |
@@ -672,17 +672,27 @@ export function createMicroiV8(options = {}) {
672
672
  return expiresAt - now <= lead;
673
673
  }
674
674
 
675
- function handleReturnedToken(headers) {
675
+ function isSameToken(left, right) {
676
+ return normalizeBearer(left) === normalizeBearer(right);
677
+ }
678
+
679
+ function handleReturnedToken(headers, requestToken, authEnabled) {
676
680
  const auth = getHeaderValue(headers, 'authorization') || getHeaderValue(headers, 'token');
677
681
  const token = normalizeBearer(auth);
678
- if (token) setToken(token);
682
+ if (!token) return;
683
+ // 登录等匿名请求允许建立新会话;受保护请求只能续签自己发起时的会话。
684
+ // 否则登录前的慢响应可能把刚登录得到的新 Token 覆盖回旧 Token。
685
+ if (!authEnabled || isSameToken(getToken(), requestToken)) setToken(token);
679
686
  }
680
687
 
681
- function handleAuthExpired(body) {
688
+ function handleAuthExpired(body, requestToken) {
689
+ // 该响应属于已经被替换的旧会话时,不得清理当前的新登录态。
690
+ if (!isSameToken(getToken(), requestToken)) return false;
682
691
  clearToken();
683
692
  if (typeof config.onAuthExpired === 'function') {
684
693
  config.onAuthExpired(body, client);
685
694
  }
695
+ return true;
686
696
  }
687
697
 
688
698
  // 所有相对地址默认走 apiBase,必要时自动追加 OsClient。
@@ -725,6 +735,8 @@ export function createMicroiV8(options = {}) {
725
735
  async function request(options = {}) {
726
736
  const method = String(options.method || 'POST').toUpperCase();
727
737
  let fullUrl = buildUrl(options.url || options.path || '');
738
+ const authEnabled = options.auth !== false;
739
+ const requestToken = authEnabled ? getToken() : '';
728
740
  const headers = buildHeaders(options);
729
741
  const data = options.data === undefined ? {} : options.data;
730
742
  const timeout = options.timeout || config.timeout;
@@ -776,14 +788,17 @@ export function createMicroiV8(options = {}) {
776
788
  const statusCode = response.statusCode || response.status || 200;
777
789
  const body = response.data === undefined ? response.body : response.data;
778
790
  const headersReturned = response.header || response.headers || {};
779
- handleReturnedToken(headersReturned);
780
791
 
781
- if (options.auth !== false && isAuthExpired(body, statusCode)) {
782
- handleAuthExpired(body);
792
+ if (authEnabled && isAuthExpired(body, statusCode)) {
793
+ const expiredCurrentSession = handleAuthExpired(body, requestToken);
794
+ // 登录前发出的旧请求可以正常失败,但不能弹过期框、跳登录或清理新 Token。
795
+ if (!expiredCurrentSession) throw body || new Error('旧登录会话已失效');
783
796
  if (options.silentError !== true) toast((body && body.Msg) || '登录已过期');
784
797
  throw body || new Error('登录已过期');
785
798
  }
786
799
 
800
+ handleReturnedToken(headersReturned, requestToken, authEnabled);
801
+
787
802
  if (statusCode >= 400) {
788
803
  const error = body || new Error(`请求失败: ${statusCode}`);
789
804
  if (options.silentError !== true) toast((body && body.Msg) || `请求失败: ${statusCode}`);
@@ -852,7 +867,7 @@ export function createMicroiV8(options = {}) {
852
867
  }
853
868
  }).then((result) => {
854
869
  if (result && result.Code !== 1 && isAuthExpired(result)) {
855
- handleAuthExpired(result);
870
+ handleAuthExpired(result, oldToken);
856
871
  }
857
872
  return result;
858
873
  }).finally(() => {
@@ -28,9 +28,10 @@ V8.OsClientNetwork // 'Intranet' / 'Outernet'
28
28
  V8.OsClientModel // 当前租户 SaaS 配置的脱敏副本
29
29
  V8.ClientModel // OsClientModel 的兼容别名,同样是脱敏副本
30
30
  V8.SysConfig // 当前租户 sys_config 的独立脱敏副本
31
+ V8.SysConfig.PublicSettings // 当前租户 mci_system_setting 的动态公开投影
31
32
  ```
32
33
 
33
- `V8.SysConfig` 与 `V8.FormEngine.GetSysConfig(...)` 不暴露 `ClientSecrets`、`PwdV8`、`GlobalServerV8Code` 或疑似凭据字段;子租户显式传其它 `OsClient` 也会被强制改回当前租户。
34
+ `V8.SysConfig` 与 `V8.FormEngine.GetSysConfig(...)` 不暴露 `ClientSecrets`、`PwdV8`、`GlobalServerV8Code` 或疑似凭据字段;子租户显式传其它 `OsClient` 也会被强制改回当前租户。`PublicSettings` 由每条设置的 `IsPublic` 动态决定,但 Secret 及固定敏感 Key 规则永远优先。
34
35
 
35
36
  ### V8.OsClientModel 常用字段
36
37
 
@@ -39,7 +40,7 @@ V8.OsClientModel.SysTitle // 租户系统标题
39
40
  V8.OsClientModel.DbType // 非敏感数据库类型
40
41
  V8.OsClientModel.HDFS // 'Aliyun' / 'MinIO' / 'S3'
41
42
  V8.OsClientModel.AliOssPublicDomain // 可公开的文件域名
42
- // 当前租户自行扩展的业务集成字段仍可读取
43
+ // 当前租户自行扩展的业务字段只作存量兼容;新增配置使用 mci_system_setting
43
44
 
44
45
  // 以下基础设施字段不会注入 V8:
45
46
  // DbConn / DbReadConn / AuthSecret
@@ -49,11 +50,11 @@ V8.OsClientModel.AliOssPublicDomain // 可公开的文件域名
49
50
 
50
51
  ## 平台级配置与主租户规则
51
52
 
52
- `sys_osclients` 既保存每个租户自己的数据库、Redis、第三方密钥等配置,也可以承载影响整个 API 进程的平台级配置。平台级配置必须遵守“主租户为准、子租户只能降额隔离”的规则:
53
+ 主库 `sys_osclients` 保存租户数据库/Redis/存储路由及影响整个 API 进程的平台级配置;目标租户建立上下文后,`sys_config` 和 `mci_system_setting` 从该租户自己的数据库读取。平台级配置必须遵守“主租户为准、子租户只能降额隔离”的规则:
53
54
 
54
55
  - 所有可变业务逻辑默认必须由接口引擎编排,包括但不限于租户开通、开库、初始化、归属修复、官网个人中心、付费额度等 SaaS 业务流程。C# 后端只暴露原子 V8 能力,例如建库、导入空库模板、复制 `sys_config`、刷新 SaaS 缓存、补偿回滚、字段兜底等;不要把可变业务分支写死到 Controller 或 `TenantProvisioningService` 这类后端定制代码里。接口引擎缺少能力时,优先扩展 `V8.Method`/V8 引擎原子函数,再由接口引擎调用。
55
56
  - 主租户由运行环境决定:优先读取环境变量 `OsClient`,其次读取 `appsettings.json` 的 `AppSettings:OsClient`。只有这条主租户 `sys_osclients` 数据中的平台级字段会作为全局配置生效。
56
- - API 启动配置只有十项白名单:`OsClient`、`OsClientType`、`OsClientNetwork`、`OsClientDbType`、`OsClientDbConn`、`OsClientRedisHost`、`OsClientRedisPort`、`OsClientRedisPwd`、`OsClientRedisDataBase`、`OsClientDbMongoConn`。除这十项外,普通业务、运行参数、密钥路径、重试、限额和安全策略统一从主租户 `sys_osclients` 或按租户从 `sys_config` 读取,未配置时使用代码安全默认值;官方 License 恢复次数/间隔与固定私钥挂载 `/app/microi_private.pem` 是信任链例外,禁止创建对应 SaaS 字段。禁止再增加 `MICROI_*`、`DOS_ORM_*`、自定义 `AppSettings` 节点或动态名称的环境变量读取。节点身份由平台自动生成。
57
+ - API 启动配置只有十项白名单:`OsClient`、`OsClientType`、`OsClientNetwork`、`OsClientDbType`、`OsClientDbConn`、`OsClientRedisHost`、`OsClientRedisPort`、`OsClientRedisPwd`、`OsClientRedisDataBase`、`OsClientDbMongoConn`。除这十项外,部署/节点级运行参数与基础设施秘密从主控 `sys_osclients` 读取;允许子租户自行维护的业务开关、OAuth/第三方集成和展示设置从该租户 `sys_config` / `mci_system_setting` 读取,未配置时使用代码安全默认值。官方 License 恢复次数/间隔与固定私钥挂载 `/app/microi_private.pem` 是信任链例外。禁止再增加 `MICROI_*`、`DOS_ORM_*`、自定义 `AppSettings` 节点或动态名称的环境变量读取。节点身份由平台自动生成。
57
58
  - `ASPNETCORE_*`、`DOTNET_*` 仅用于 .NET 宿主;构建、安装、测试、MCP、发布脚本可使用自身进程变量,但 API 生产代码不得把它们当业务配置。新增 SaaS 运行字段必须配套独立或既有 Tab、幂等升级、缓存刷新、敏感字段脱敏、子租户不继承和源码扫描测试。
58
59
  - 文件上传的租户业务开关与额度按“当前租户 `sys_osclients` → 代码默认值”解析;平台固定灾难保护、HTTP/Multipart/Form 和反向代理上限不可由租户覆盖,也不要求安装者维护额外上传环境变量。
59
60
  - 类似 MQTT 端口、PressureGuard、V8Limits、OrmLimits、StartupLimits、SecurityGuard 这类影响整进程资源的配置,不能让每个子租户各自抬高全局上限。子租户同名隔离字段只能降低自己的并发、等待时间或资源额度,用于隔离弱租户、试用租户或异常租户。
@@ -139,18 +140,20 @@ var erpUrl = (V8.OsClientNetwork === 'Intranet')
139
140
  : 'https://erp.public.com/api';
140
141
  ```
141
142
 
142
- ## 第三方密钥放 OsClientModel(不要硬编码)
143
+ ## 第三方密钥放租户动态设置(不要硬编码)
143
144
 
144
145
  ```javascript
145
146
  // ❌ 危险:密钥写在代码里,所有租户共用,无法独立轮换
146
147
  var ak = 'AKIDxxxxxxxx';
147
148
 
148
- // ✅ 正确:每个租户在 sys_osclients 表中配置自己的业务集成密钥
149
- var ak = V8.OsClientModel.WxPayMchKey;
150
- var secret = V8.OsClientModel.WxPaySecret;
151
- ```
152
-
153
- > 在表单引擎中给 `sys_osclients` 添加租户自有业务字段(如 `WxPayMchKey`),可通过 `V8.OsClientModel.字段名` 访问。共享基础设施字段由服务端强制移除,不能用自定义同义字段绕过安全代理。
149
+ // ✅ 普通可公开业务值:每个租户在 mci_system_setting 动态维护
150
+ var loginName = V8.SysConfig.PublicSettings['Login.Gitee.Name'];
151
+
152
+ // ✅ Secret:由固定协议的可信后端能力读取并直接调用供应商
153
+ // V8 只传业务参数,不获得 ak/secret 原文。
154
+ ```
155
+
156
+ > `mci_system_setting` 位于每个租户自己的数据库。普通设置可以逐条动态公开到 `V8.SysConfig.PublicSettings`;Secret 保存认证密文,普通 V8/FormEngine/匿名/访问密钥会话不能读取 `SecretCipher` 或调用通用解密器。`sys_osclients` 自定义业务字段只保留存量兼容;共享基础设施字段由服务端强制移除,不能用自定义同义字段绕过安全代理。
154
157
 
155
158
  ## 用户扩展字段访问(同理)
156
159
 
@@ -169,6 +172,7 @@ SELECT * FROM Contact WHERE OwnerId = $CurrentUser.Id$ AND Spouse = $CurrentUser
169
172
  ❌ 绕开 `V8.Cache` 使用底层 Redis → 租户数据串号(V8 已不再暴露底层句柄)
170
173
  ❌ MongoDB DbName 不带 OsClient → 数据混淆
171
174
  ❌ 把 OsClientModel 字段直接返回给前端 → 密钥泄漏
175
+ ❌ 查询 `mci_system_setting.SecretCipher` 或给 V8 暴露通用解密器 → 密钥边界失效
172
176
  ❌ 在前端硬编码 OsClient → 一改全改,应通过 token/URL 自动识别
173
177
  ❌ 跨租户操作不验证当前用户权限 → 越权风险
174
178
  ❌ 子租户缺少 MQ/MQTT/Search 独立凭据时回退主账号 → 全平台越权
@@ -1,29 +1,32 @@
1
1
  ---
2
2
  name: v8-security
3
- description: Microi V8 安全指南。用于审查 DiyToken 与权限、可逆业务秘密、Passkey/人脸步进验证、接口引擎安全、密钥管理、SQL 注入、匿名端点、文件上传和租户隔离。
3
+ description: Microi V8 安全指南。用于审查 DiyToken 与权限、可逆业务秘密、Passkey/TOTP/人脸步进验证、接口引擎安全、密钥管理、SQL 注入、匿名端点、文件上传和租户隔离。
4
4
  ---
5
5
 
6
6
  # Microi V8 安全最佳实践
7
7
 
8
8
  你正在开发 Microi 吾码平台的 V8 引擎代码,必须遵守以下安全规范。
9
9
 
10
- ## 0. 租户业务密钥放 OsClientModel(基础设施密钥由服务端托管)
11
-
12
- 第三方密钥(微信、支付宝、OpenAI、阿里云、ERP、SMTP)**禁止**硬编码在 V8 代码或前端。受保护的 `sys_osclients` 表可扩展租户自有业务集成字段;只有可信控制面能维护,普通角色不能通过 FormEngine 直接读写:
10
+ ## 0. 租户动态系统设置与密钥边界
11
+
12
+ 第三方密钥(微信、支付宝、OpenAI、阿里云、ERP、SMTP)**禁止**硬编码在 V8 代码或前端。新增租户业务配置使用当前租户数据库的 `mci_system_setting`;数据库、Redis、MongoDB、MinIO、MQ 等部署控制面仍由主库 `sys_osclients` 托管,子租户不能修改。
13
13
 
14
14
  ```javascript
15
- // ✅ 正确
16
- var openaiKey = V8.OsClientModel.OpenAIKey;
17
- var wxSecret = V8.OsClientModel.WxPaySecret;
18
- var smtpPwd = V8.OsClientModel.SmtpPassword;
15
+ // ✅ 浏览器/前端 V8 只能读取管理员明确公开的普通设置
16
+ var loginName = V8.SysConfig.PublicSettings['Login.Gitee.Name'];
17
+
18
+ // Secret 由固定协议的可信后端原子能力读取和使用
19
+ // V8 只传业务参数,不能拿到 ClientSecret 原文。
19
20
 
20
21
  // ❌ 危险:密钥泄漏 / 跨租户串号
21
22
  var openaiKey = 'sk-xxxxxxxxxx';
22
23
  ```
23
24
 
24
- > `V8.OsClientModel` 与兼容别名 `V8.ClientModel` 均为独立脱敏副本:数据库连接、AuthSecret、Redis、对象存储、MQ、MQTT、Search 的地址与凭据不会注入脚本。当前租户自有的微信、支付、ERP 等业务密钥仍可能存在,因此仍严禁把整个对象或单个密钥返回前端。
25
+ `V8.OsClientModel` 与兼容别名 `V8.ClientModel` 均为独立脱敏副本:数据库连接、AuthSecret、Redis、对象存储、MQ、MQTT、Search 的地址与凭据不会注入脚本。存量租户业务字段只作兼容,新增 Secret 不得继续依赖 `V8.OsClientModel`。
26
+
27
+ `V8.SysConfig` 也是独立脱敏副本,`ClientSecrets`、`PwdV8`、`GlobalServerV8Code` 及疑似 Password/Secret/Token/Key/Connection 字段不会注入脚本。`V8.SysConfig.PublicSettings` 来自当前租户 `mci_system_setting`:每条记录可以动态设置 `IsPublic`,但 `IsSecret=1` 或 Key 命中 Password、Secret、Token、Credential、PrivateKey、AccessKey、ApiKey、ConnectionString、DbConn、Redis、MinIO、ClientSecret 等固定敏感片段时永远失败关闭。子租户调用 `V8.FormEngine.GetSysConfig(...)` 时服务端会强制使用当前 `OsClient`,不能借缓存命中读取主租户配置。
25
28
 
26
- `V8.SysConfig` 也是独立脱敏副本,`ClientSecrets`、`PwdV8`、`GlobalServerV8Code` 及疑似 Password/Secret/Token/Key/Connection 字段不会注入脚本。子租户调用 `V8.FormEngine.GetSysConfig(...)` 时服务端会强制使用当前 `OsClient`,不能借缓存命中读取主租户配置。
29
+ Secret 只通过租户管理员专用端点写入租户绑定的认证密文。列表不返回密文或原文;临时显示必须消费 Passkey/TOTP/严格人脸一次性票据,设置 `no-store`,30 秒清除,审计不含原文。普通 FormEngine、可编辑 V8、匿名请求和访问密钥会话不得读取 `SecretCipher` 或获得通用解密器。
27
30
 
28
31
  共享基础设施只能通过受控能力访问:`V8.Cache` 自动绑定 `Microi:{OsClient}:*`,文件路径绑定 `/{OsClient}/...`,RabbitMQ 队列绑定 `microi.{OsClient}.*`,MQTT Topic 绑定 `tenant/{OsClient}/...`,Search 索引绑定 `{OsClient}_*`。V8 不得获得 Redis `IDatabase`、HDFS `ClientModel` 或原始基础设施配置。
29
32
 
@@ -292,9 +295,9 @@ V8.NotSaveField.push('SecretPlain');
292
295
  - 页面默认掩码,点击显示需二次确认,失焦/超时/路由离开后清除;禁止复制到 URL、LocalStorage 或前端日志。
293
296
  - DES 是存量兼容格式。新高价值秘密优先由可信 C# 原子能力使用带版本的现代认证加密和集中密钥管理,V8 仍只编排授权显示,不能获取主密钥。
294
297
 
295
- ### Passkey、人脸与敏感操作票据
298
+ ### Passkey、Authenticator、人脸与敏感操作票据
296
299
 
297
- 前端 V8 使用 `V8.Identity.Verify({Purpose,ActionHash,Method})` 完成人机交互,后端必须从数据库重读权威业务字段、按稳定版本/顺序重算 `ActionHash`,再消费票据:
300
+ 前端 V8 使用 `V8.Identity.Verify({Purpose,ActionHash,Method,Code})` 完成人机交互;`Method=Totp` `Code` 是用户当前看到的 6 位动态口令。后端必须从数据库重读权威业务字段、按稳定版本/顺序重算 `ActionHash`,再消费票据:
298
301
 
299
302
  ```javascript
300
303
  var actionHash = V8.EncryptHelper.Sha256Hex(canonicalCommand);
@@ -310,8 +313,12 @@ if (verified.Code !== 1) return verified;
310
313
  - 前端提交的摘要、`Verified=true`、认证器名称或方法不能作为授权事实;访问密钥会话不能使用。
311
314
  - 票据只证明近期强身份,不代替菜单/表/行权限、业务状态机、事务、幂等或审计。
312
315
  - 设备指纹/Face ID/Windows Hello 优先走 WebAuthn/Passkey,不需要模型 Docker;只有严格服务端人脸/活体检测才通过 `Microi Face Gateway v1` 接入独立服务。
316
+ - 标准 TOTP Authenticator 不需要 Docker,但 6 位码不能单独标识账号:登录时仍需账号;密钥只以租户绑定的认证密文保存,并用共享限流和已接受计数器阻止暴力尝试与重放。
317
+ - 每个 Passkey/TOTP 分别保存 `AllowPasswordlessLogin` 与 `AllowStepUp`;登录和票据签发都必须服务端重新读取策略,不能只依赖个人中心开关的前端状态。
318
+ - Gitee、微信、GitHub 等外部身份只允许登录已绑定的吾码用户;禁止按邮箱/昵称自动合并账号。OAuth state 与登录票据保存在共享 Redis、单次消费并绑定 `OsClient`/Provider/Origin;固定端点白名单,ClientSecret 只由可信后端读取,最终仍签发 DiyToken。
319
+ - 官方升级通过 `app.microi.saas-engine` 应用包幂等安装身份表、`mci_system_setting`、`mci_user_external_identity`、默认设置、个人中心和系统设置微服务。默认设置按 `ConfigKey + InsertIfMissing` 补齐,不覆盖 `ValueSource=Tenant` 的租户值;Passkey、TOTP、总开关和改密步进验证默认开启,严格人脸及各外部 Provider 默认关闭。
313
320
  - 完整表、SaaS 字段、API 和启用顺序见 `microi.doc/docs/doc/more/identity-verification.md`。
314
- - 身份验证 HTTP 控制面统一位于 `/api/identityverification/`,业务页面优先使用 `V8.Identity`,不要自行复制 WebAuthn 序列化代码。
321
+ - 身份验证 HTTP 控制面位于 `/api/identityverification/`,外部登录位于 `/api/externallogin/`,动态设置位于 `/api/tenantsystemsettings/`;业务页面优先使用 `V8.Identity` 或官方个人中心,不要自行复制 WebAuthn/OAuth 协议代码。
315
322
 
316
323
  ### 脱敏返回
317
324
 
@@ -118,7 +118,7 @@
118
118
  | `V8.Identity.GetCapabilities()` | 读取当前租户强身份能力和本人登记状态 |
119
119
  | `V8.Identity.CreateActionHash(value)` | 为稳定业务命令生成 SHA-256 摘要 |
120
120
  | `V8.Identity.RegisterPasskey(options?)` | 登记当前用户 Passkey |
121
- | `V8.Identity.Verify({Purpose,ActionHash,Method})` | 完成 Passkey/严格人脸验证并取得一次性后端票据 |
121
+ | `V8.Identity.Verify({Purpose,ActionHash,Method,Code?})` | 完成 Passkey、Authenticator TOTP 或严格人脸验证并取得一次性后端票据;Totp 需 6 位 Code |
122
122
 
123
123
  扫码应优先接收 Promise 返回值;兼容代码可在调用后读取 `V8.ScanCodeRes`。
124
124
  `V8.Identity` 是强身份验证模块。`V8.Identity.Verify` 的成功结果不能直接授权业务;后端必须重读权威数据、重算摘要并调用 `V8.Method.ConsumeIdentityVerificationTicket`。
@@ -50,7 +50,7 @@
50
50
  | `V8.Method.GetCurrentToken(token,osClient)` | 读取当前 Token 对象;不透传前端 |
51
51
  | `V8.Method.RefreshLoginUser(userId,osClient)` | 刷新用户登录缓存 |
52
52
  | `V8.Method.ClearUserLoginInfo(userId,osClient)` | 管理员吊销用户全部终端 Token |
53
- | `V8.Method.ConsumeIdentityVerificationTicket({Ticket,Purpose,ActionHash})` | 按当前 DiyToken 用户、租户、用途和操作摘要原子消费一次性 Passkey/人脸票据 |
53
+ | `V8.Method.ConsumeIdentityVerificationTicket({Ticket,Purpose,ActionHash})` | 按当前 DiyToken 用户、租户、用途和操作摘要原子消费一次性 Passkey/TOTP/人脸票据 |
54
54
  | `V8.Method.GetPrivateFileUrl({FilePathName})` | 签发当前租户短期私有文件代理地址 |
55
55
  | `V8.Method.Upload(options)` | 受配额限制的上传 |
56
56
  | `V8.Method.AddSysLog(options)` | 结构化系统日志 |
@@ -160,7 +160,7 @@ AI 新增或修改 Microi 配置文件时,凡是面向开发者、部署人员
160
160
  ## 后端 API 配置白名单与 SaaS 单一事实源(强制)
161
161
 
162
162
  - `Microi.net.Api` 的 `AppSettings` 与同名容器环境变量只允许:`OsClient`、`OsClientType`、`OsClientNetwork`、`OsClientDbType`、`OsClientDbConn`、`OsClientRedisHost`、`OsClientRedisPort`、`OsClientRedisPwd`、`OsClientRedisDataBase`、`OsClientDbMongoConn`。
163
- - 除上述十项外,任何业务开关、重试、超时、限额、安全策略、密钥或可执行文件路径通常都必须进入 SaaS 引擎 `sys_osclients` 的合适 Tab,并提供幂等升级、默认值、缓存刷新、敏感字段脱敏和子租户隔离。官方 License 信任链是固定例外:恢复重试次数/间隔使用代码常量,签发私钥固定只读挂载 `/app/microi_private.pem`,不得建立对应 SaaS 字段。禁止新增 `MICROI_*`、`DOS_ORM_*`、额外 `AppSettings` 节点或通用动态环境变量读取。
163
+ - 除上述十项外,不得新增 API 业务环境变量或 `AppSettings` 节点。影响整个部署/节点或决定租户基础设施路由的开关、超时、限额、安全策略和密钥进入主控 `sys_osclients`;允许每个子租户自行维护的 OAuth、业务集成和展示设置进入该租户数据库的 `mci_system_setting`。两者都必须提供幂等升级、默认值、缓存刷新、敏感字段脱敏和租户隔离。官方 License 信任链是固定例外:恢复重试次数/间隔使用代码常量,签发私钥固定只读挂载 `/app/microi_private.pem`。禁止新增 `MICROI_*`、`DOS_ORM_*`、额外 `AppSettings` 节点或通用动态环境变量读取。
164
164
  - `ASPNETCORE_*`、`DOTNET_*` 是框架宿主配置;`PW_*`、MCP、构建、安装器和发布脚本变量只服务各自工具进程。它们不能成为生产 API 的业务配置入口。
165
165
  - 修改后必须用源码测试扫描生产 `.cs`、API `appsettings.json` 及在线/离线 Compose,精确断言十项白名单。不能用注释约定代替自动化守卫。
166
166
 
@@ -170,8 +170,9 @@ AI 新增或修改 Microi 配置文件时,凡是面向开发者、部署人员
170
170
  - 登录密码的新存储必须使用后端带盐、可调成本的专用密码哈希。存量 `PwdEncode=DES` 的管理员显示密码只是兼容能力,不得扩展给普通 V8、FormEngine、匿名或访问密钥会话。
171
171
  - 业务明确要求再次显示原文的设备口令、第三方业务账号密码等字段,允许使用吾码可逆加密兼容机制。保存只在可信后端加密;列表/导出默认掩码;显示明文走独立授权动作,校验 DiyToken、租户和业务权限,返回 `no-store`,记录不含明文的审计,失焦/超时后清除。
172
172
  - DES 是现有兼容格式,不得宣称能抵抗服务器所有者或代码执行者。新高价值秘密优先使用带版本的现代认证加密与集中密钥管理;基础设施密钥仍不得进入可编辑 V8。
173
- - 登录后的敏感操作优先用 `V8.Identity.Verify` 申请 Passkey/严格人脸一次性票据,接口引擎从权威数据重算 `ActionHash` 后调用 `V8.Method.ConsumeIdentityVerificationTicket` 原子消费。票据不能代替菜单/表/行权限、状态机、幂等、事务或审计。
174
- - Windows Hello、Touch ID、Face ID 和 Android 设备验证优先采用 WebAuthn/Passkey,不增加模型服务;只有服务端严格人脸与活体检测才接入独立 `Microi Face Gateway v1` 云服务或 Docker/集群。完整规范读取 `microi.skills/v8-security/SKILL.md` 与 `microi.doc/docs/doc/more/identity-verification.md`。
173
+ - 登录后的敏感操作优先用 `V8.Identity.Verify` 申请 Passkey、Authenticator TOTP 或严格人脸一次性票据,接口引擎从权威数据重算 `ActionHash` 后调用 `V8.Method.ConsumeIdentityVerificationTicket` 原子消费。票据不能代替菜单/表/行权限、状态机、幂等、事务或审计。
174
+ - Windows Hello、Touch ID、Face ID 和 Android 设备验证优先采用 WebAuthn/Passkey;Microsoft/Google Authenticator 采用标准 TOTP,两者都不增加模型服务。只有服务端严格人脸与活体检测才接入独立 `Microi Face Gateway v1` 云服务或 Docker/集群。完整规范读取 `microi.skills/v8-security/SKILL.md` 与 `microi.doc/docs/doc/more/identity-verification.md`。
175
+ - 外部登录统一在登录页【登录方式】中展示;Gitee、微信、GitHub 等 Provider 只登录个人中心已绑定的吾码用户,最终签发 DiyToken。Provider 固定协议端点,租户自己的 ClientId/ClientSecret 放 `mci_system_setting`,Secret 不进入 `V8.SysConfig.PublicSettings`、普通 V8 或浏览器。
175
176
  - 一键安装恢复客户旧库时只允许定位精确主租户三元组;缺失则幂等创建,重复则停止,不能批量重写其它子租户。新主租户行不得持久化数据库、MongoDB 或 Redis 连接,安装器对 MinIO/OCR 等业务配置的后续更新也必须带同一三元组、活动状态条件并做唯一回读。
176
177
 
177
178
  ## 多语言优先约定
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microi.net/cli",
3
- "version": "4.7.4",
3
+ "version": "4.7.6",
4
4
  "description": "Microi吾码 AI 开发命令行:服务器连接、登录、AI/MCP 初始化与 V8 资源同步",
5
5
  "license": "MIT",
6
6
  "homepage": "https://microi.net/doc/v8-engine/vs-code-plugin.html",