@microi.net/cli 5.8.5 → 5.8.7
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.
- package/.codebuddy-plugin/marketplace.json +2 -2
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.workbuddy-plugin/marketplace.json +2 -2
- package/.workbuddy-plugin/plugin.json +1 -1
- package/LICENSE +21 -21
- package/README.md +71 -71
- package/assets/build-meta.json +7 -7
- package/assets/feature-matrix.json +138 -138
- package/assets/logo.svg +4 -4
- package/cordis.patch.yml +1 -1
- package/package.json +1 -1
- package/scripts/mcp-codex-stdio-adapter.js +0 -0
- package/scripts/mcp-server.js +1 -1
- package/scripts/microi-cli.js +66 -65
- package/scripts/microi-codex-broker.js +450 -450
- package/scripts/microi-codex-router.js +618 -618
- package/scripts/microi-skills.meta.json +384 -384
- package/skills/.microi-skills-version.json +2 -2
- package/skills/.progressive-disclosure-manifest.json +21 -21
- package/skills/README.md +287 -287
- package/skills/ai-engine/SKILL.md +269 -265
- package/skills/ai-engine/agents/openai.yaml +4 -4
- package/skills/ai-engine/references/ai-employees.md +48 -48
- package/skills/ai-engine/references/self-hosted-digital-human.md +59 -59
- package/skills/ai-platform-governance/SKILL.md +177 -177
- package/skills/ai-platform-governance/references/progressive-01-/345/212/237/350/203/275/345/274/200/345/205/263.md +190 -190
- package/skills/app-store/SKILL.md +525 -525
- package/skills/app-store/agents/openai.yaml +4 -4
- package/skills/business-blueprint/SKILL.md +193 -193
- package/skills/datasource-engine/SKILL.md +93 -93
- package/skills/datasource-engine/agents/openai.yaml +4 -4
- package/skills/dos-orm/SKILL.md +97 -95
- package/skills/dos-orm/references/api-reference.md +229 -229
- package/skills/email-engine/SKILL.md +81 -81
- package/skills/email-engine/references/v8-email.md +34 -34
- package/skills/job-engine/SKILL.md +176 -176
- package/skills/job-engine/agents/openai.yaml +4 -4
- package/skills/message-notification/SKILL.md +156 -156
- package/skills/message-notification/agents/openai.yaml +5 -5
- package/skills/message-notification/references/contracts.md +102 -102
- package/skills/microi/SKILL.md +14 -14
- package/skills/microi-ai-app-auth.js +652 -652
- package/skills/microi-ai-application/SKILL.md +115 -115
- package/skills/microi-ai-application/agents/openai.yaml +4 -4
- package/skills/microi-ai-application/references/frontend-baseline.md +164 -164
- package/skills/microi-client-frontend/SKILL.md +246 -244
- package/skills/microi-client-frontend/references/progressive-01-3-/345/212/250/346/200/201/346/214/211/351/222/256/347/263/273/347/273/237.md +144 -144
- package/skills/microi-client-frontend/references/progressive-02-8-/350/277/220/350/241/214/346/227/266/351/253/230/351/242/221/345/235/221/345/244/215/347/233/230.md +196 -196
- package/skills/microi-client-frontend/references/progressive-03-vue3-/345/211/215/347/253/257/345/276/256/346/234/215/345/212/241/345/256/277/344/270/273/350/247/204/345/210/231.md +167 -167
- package/skills/microi-codex/SKILL.md +102 -100
- package/skills/microi-codex-installer/SKILL.md +231 -231
- package/skills/microi-codex-installer/agents/openai.yaml +7 -7
- package/skills/microi-datasource-mapping/SKILL.md +122 -122
- package/skills/microi-db-schema/SKILL.md +175 -175
- package/skills/microi-db-schema/agents/openai.yaml +4 -4
- package/skills/microi-db-schema/references/core-tables.md +695 -695
- package/skills/microi-db-schema/references/form-component-options.md +256 -256
- package/skills/microi-db-schema/references/schema-overview.md +202 -202
- package/skills/microi-db-schema/references/schema.md +646 -646
- package/skills/microi-db-schema/references/table-catalog.md +1599 -1599
- package/skills/microi-deployment/SKILL.md +222 -220
- package/skills/microi-deployment/references/deployment-matrix.md +109 -109
- package/skills/microi-docs-coverage/SKILL.md +133 -133
- package/skills/microi-docs-coverage/references/capability-map.md +91 -91
- package/skills/microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs +894 -894
- package/skills/microi-form-engine/SKILL.md +333 -333
- package/skills/microi-form-engine/references/component-catalog.md +218 -218
- package/skills/microi-form-engine/references/data-source-events.md +124 -124
- package/skills/microi-form-layout/SKILL.md +205 -205
- package/skills/microi-form-layout/references/progressive-01-3-/344/270/211/347/247/215/345/210/206/347/273/204/347/232/204/345/255/230/345/202/250/344/270/216/351/205/215/347/275/256.md +235 -235
- package/skills/microi-frontend-sdk/SKILL.md +194 -194
- package/skills/microi-frontend-sdk/references/progressive-01-token-/345/275/223/345/211/215/347/231/273/345/275/225/347/224/250/346/210/267/344/270/216/345/275/223/345/211/215/347/273/210/347/253/257/347/231/273/345/275/225/345/215/217/350/256/256.md +176 -176
- package/skills/microi-left-right-layout/SKILL.md +141 -141
- package/skills/microi-microservice/SKILL.md +328 -326
- package/skills/microi-microservice/references/runtime-delivery.md +278 -278
- package/skills/microi-mobile-app-quality/SKILL.md +185 -185
- package/skills/microi-mobile-app-quality/references/progressive-01-4-/351/207/215/350/246/201/346/214/211/351/222/256/345/277/205/351/241/273/345/270/246/345/233/276/346/240/207.md +213 -213
- package/skills/microi-mobile-app-quality/references/progressive-02-9-/344/270/273/351/242/230/345/210/207/346/215/242/345/277/205/351/241/273/347/234/237/345/256/236/344/270/224/345/205/250/345/261/200/347/224/237/346/225/210.md +128 -128
- package/skills/microi-solution-quotation/SKILL.md +78 -78
- package/skills/microi-solution-quotation/agents/openai.yaml +4 -4
- package/skills/microi-solution-quotation/scripts/build_solution_quote.py +296 -296
- package/skills/microi-sso/SKILL.md +96 -90
- package/skills/microi-sso/references/acceptance.md +49 -49
- package/skills/microi-sso/references/configuration-and-security.md +53 -53
- package/skills/microi-sso/references/inbound.md +53 -53
- package/skills/microi-sso/references/outbound.md +39 -39
- package/skills/microi-system-delivery/SKILL.md +137 -137
- package/skills/microi-system-delivery/references/progressive-01-/346/240/207/345/207/206/345/267/245/344/275/234/346/265/201.md +193 -193
- package/skills/microi-system-delivery/references/progressive-02-/350/207/252/345/212/250/345/214/226/346/265/213/350/257/225/345/277/205/351/241/273/350/246/206/347/233/226/347/232/204/345/235/221.md +217 -217
- package/skills/microi-ui/SKILL.md +192 -192
- package/skills/microi-ui/references/progressive-01-/347/247/273/345/212/250/347/253/257/345/234/272/346/231/257/350/223/235/345/233/276.md +183 -183
- package/skills/microi-uniapp-frontend/SKILL.md +193 -193
- package/skills/microi-uniapp-frontend/references/progressive-01-/347/247/273/345/212/250/347/253/257/345/210/206/347/261/273-/345/217/214/346/240/217/345/210/227/350/241/250/347/213/254/347/253/213/346/273/232/345/212/250.md +225 -225
- package/skills/microi-uniapp-frontend/references/progressive-02-/345/205/263/351/224/256/344/270/232/345/212/241/350/265/204/344/272/247/344/270/215/345/276/227/351/273/230/350/256/244/351/200/211/344/270/255.md +154 -154
- package/skills/microi.v8.js +1921 -1921
- package/skills/module-engine/SKILL.md +255 -255
- package/skills/module-engine/references/module-config.md +204 -204
- package/skills/ocr-engine/SKILL.md +113 -113
- package/skills/ocr-engine/agents/openai.yaml +4 -4
- package/skills/page-engine/SKILL.md +206 -206
- package/skills/page-engine/examples/compact-dashboard.json +1444 -1444
- package/skills/page-engine/references/progressive-01-/346/211/200/346/234/211/347/273/204/344/273/266/347/261/273/345/236/213.md +234 -234
- package/skills/page-engine/references/progressive-02-/347/211/210/346/234/254/345/216/206/345/217/262-/345/271/266/345/217/221/344/277/235/345/255/230/344/270/216/345/233/236/346/273/232.md +60 -60
- package/skills/performance-testing/SKILL.md +221 -221
- package/skills/playwright-e2e/SKILL.md +196 -196
- package/skills/playwright-e2e/references/progressive-01-/345/205/250/350/207/252/345/212/250/347/231/273/345/275/225-/345/205/215/351/252/214/350/257/201/347/240/201-/344/275/206/344/270/215/345/205/215/345/257/206/347/240/201-/345/277/205/350/257/273.md +173 -173
- package/skills/playwright-e2e/references/progressive-02-/346/226/207/345/255/227/345/257/271/346/257/224/345/272/246/344/270/216/345/217/257/350/257/273/346/200/247/350/207/252/345/212/250/345/214/226/346/243/200/346/237/245-/345/277/205/345/201/232.md +183 -183
- package/skills/playwright-e2e/references/progressive-03-microi-helper-/346/250/241/346/235/277.md +221 -221
- package/skills/playwright-e2e/references/progressive-04-ci-/345/273/272/350/256/256.md +115 -115
- package/skills/print-engine/SKILL.md +259 -259
- package/skills/production-readonly-audit/SKILL.md +41 -41
- package/skills/report-engine/SKILL.md +71 -71
- package/skills/report-engine/agents/openai.yaml +4 -4
- package/skills/scripts/optimize-progressive-disclosure.mjs +204 -204
- package/skills/scripts/refresh-progressive-disclosure.mjs +64 -64
- package/skills/scripts/sync-embedded-skills.mjs +46 -46
- package/skills/scripts/validate-progressive-disclosure.mjs +57 -57
- package/skills/search-engine/SKILL.md +75 -75
- package/skills/search-engine/agents/openai.yaml +4 -4
- package/skills/spider-engine/SKILL.md +190 -190
- package/skills/system-observability/SKILL.md +249 -246
- package/skills/system-observability/references/memory-incident-triage.md +77 -77
- package/skills/translate-engine/SKILL.md +140 -140
- package/skills/translate-engine/agents/openai.yaml +4 -4
- package/skills/ui-design/SKILL.md +223 -223
- package/skills/ui-design/assets/pattern-showcase/app.js +54 -54
- package/skills/ui-design/assets/pattern-showcase/index.html +163 -163
- package/skills/ui-design/assets/pattern-showcase/styles.css +311 -311
- package/skills/ui-design/assets/templates/MCI-DESIGN.md +206 -206
- package/skills/ui-design/references/design-pattern-library.md +184 -184
- package/skills/ui-design/references/mci-design-contract.md +163 -163
- package/skills/ui-design/references/motion-and-media.md +78 -78
- package/skills/ui-design/references/product-flow-recipes.md +94 -94
- package/skills/ui-design/references/progressive-01-/351/242/234/350/211/262/344/275/223/347/263/273-css-variables-/346/224/257/346/214/201/344/270/273/351/242/230/345/210/207/346/215/242.md +218 -218
- package/skills/ui-design/references/progressive-02-/345/255/227/344/275/223.md +164 -164
- package/skills/ui-design/references/progressive-03-/345/212/250/346/225/210/350/247/204/350/214/203-/344/270/260/345/257/214/344/275/206/344/270/215/345/215/241.md +235 -235
- package/skills/ui-design/references/progressive-04-/347/273/204/344/273/266/351/243/216/346/240/274/351/200/237/346/237/245.md +152 -152
- package/skills/ui-design/references/progressive-05-/347/247/273/345/212/250/347/253/257/344/270/223/347/224/250/350/247/204/350/214/203.md +238 -238
- package/skills/ui-design/references/progressive-06-/344/270/273/351/242/230/345/210/207/346/215/242/345/256/236/347/216/260.md +194 -194
- package/skills/ui-design/references/progressive-07-/351/200/237/346/237/245-/344/273/216/345/244/264/346/220/255/345/273/272/344/270/200/344/270/252/347/247/273/345/212/250/347/253/257/351/241/265/351/235/242.md +207 -207
- package/skills/ui-design/references/progressive-08-/350/241/250/345/215/225/345/210/206/347/273/204/350/247/204/350/214/203-tabs-vs-collapsegroup-/345/274/272/345/210/266.md +142 -142
- package/skills/uniapp-mall-assets/SKILL.md +176 -176
- package/skills/unity-integration/SKILL.md +171 -171
- package/skills/unity-integration/agents/openai.yaml +4 -4
- package/skills/unity-integration/references/ai-app-delivery.md +119 -119
- package/skills/unity-integration/references/sdk-api.md +82 -82
- package/skills/unity-integration/references/toolbox-migration.md +66 -66
- package/skills/unity-integration/references/webgl-hosting.md +57 -57
- package/skills/v8-api-config/SKILL.md +388 -388
- package/skills/v8-cache-pattern/SKILL.md +312 -312
- package/skills/v8-crud-api/SKILL.md +178 -178
- package/skills/v8-crud-api/references/progressive-01-/346/237/245/350/257/242/345/210/227/350/241/250-/345/210/206/351/241/265.md +226 -226
- package/skills/v8-crud-api/references/progressive-02-where-/346/235/241/344/273/266/350/257/255/346/263/225/351/200/237/346/237/245.md +49 -49
- package/skills/v8-debugging/SKILL.md +284 -284
- package/skills/v8-explorer-tree/SKILL.md +228 -228
- package/skills/v8-export-import/SKILL.md +219 -219
- package/skills/v8-export-import/references/progressive-01-excellayout-/351/253/230/347/272/247/350/207/252/347/224/261/345/270/203/345/261/200.md +211 -211
- package/skills/v8-export-import/references/progressive-02-powerpoint-/345/257/274/345/207/272.md +202 -202
- package/skills/v8-export-import/references/progressive-03-/345/256/211/345/205/250-/346/200/247/350/203/275/346/263/250/346/204/217.md +42 -42
- package/skills/v8-file-upload/SKILL.md +284 -284
- package/skills/v8-file-upload/references/progressive-01-/345/205/254/346/234/211/346/241/266-vs-/347/247/201/346/234/211/346/241/266.md +263 -263
- package/skills/v8-file-upload/references/progressive-02-office-/346/226/207/344/273/266/345/234/250/347/272/277/347/274/226/350/276/221/347/211/210/346/234/254/345/217/267/350/247/204/345/210/231.md +161 -161
- package/skills/v8-formengine-http/SKILL.md +238 -238
- package/skills/v8-frontend-events/SKILL.md +180 -180
- package/skills/v8-frontend-events/references/bluetooth-print-api.md +135 -135
- package/skills/v8-frontend-events/references/bluetooth-print.md +258 -258
- package/skills/v8-frontend-events/references/progressive-01-/345/210/227/350/241/250/344/272/213/344/273/266.md +219 -219
- package/skills/v8-http-integration/SKILL.md +182 -182
- package/skills/v8-http-integration/references/progressive-01-get-/350/257/267/346/261/202.md +220 -220
- package/skills/v8-http-integration/references/progressive-02-/351/224/231/350/257/257/345/244/204/347/220/206/346/250/241/345/274/217.md +44 -44
- package/skills/v8-image-processing/SKILL.md +190 -190
- package/skills/v8-image-processing/agents/openai.yaml +4 -4
- package/skills/v8-image-processing/references/api-reference.md +623 -623
- package/skills/v8-menu-buttons/SKILL.md +186 -186
- package/skills/v8-menu-buttons/references/progressive-01-2-/346/214/211/351/222/256/345/257/271/350/261/241-schema.md +222 -222
- package/skills/v8-menu-buttons/references/progressive-02-8-/346/250/241/345/274/217-f-/345/220/216/345/217/260/344/273/273/345/212/241/346/214/211/351/222/256-/351/225/277/344/273/273/345/212/241.md +228 -228
- package/skills/v8-menu-buttons/references/progressive-03-10-/345/217/215/346/250/241/345/274/217-/351/201/277/345/205/215.md +104 -104
- package/skills/v8-mongodb/SKILL.md +200 -200
- package/skills/v8-mq-mqtt/SKILL.md +176 -176
- package/skills/v8-mq-mqtt/references/mqtt-production.md +342 -342
- package/skills/v8-mq-mqtt/references/progressive-01-v8-mqtt-iot-/347/211/251/350/201/224/347/275/221.md +181 -181
- package/skills/v8-mq-mqtt/scripts/check-mqtt-skill-coverage.mjs +203 -203
- package/skills/v8-saas-multi-tenant/SKILL.md +305 -305
- package/skills/v8-security/SKILL.md +210 -210
- package/skills/v8-security/references/progressive-01-2-/346/235/203/351/231/220/346/240/241/351/252/214.md +200 -200
- package/skills/v8-security/references/progressive-02-7-/346/227/245/345/277/227/350/256/260/345/275/225.md +160 -160
- package/skills/v8-sql-query/SKILL.md +302 -302
- package/skills/v8-table-event/SKILL.md +176 -176
- package/skills/v8-table-event/references/progressive-01-informv8-js-/350/241/250/345/215/225/346/211/223/345/274/200/344/272/213/344/273/266.md +216 -216
- package/skills/v8-table-event/references/progressive-02-/345/211/215/347/253/257/344/272/213/344/273/266/345/220/215-v8-eventname-/345/217/257/350/203/275/347/232/204/345/200/274.md +46 -46
- package/skills/v8-tcp-integration/SKILL.md +147 -147
- package/skills/v8-tcp-integration/agents/openai.yaml +4 -4
- package/skills/v8-template-engine/SKILL.md +167 -167
- package/skills/v8-utilities/SKILL.md +104 -104
- package/skills/v8-utilities/references/client-api-index.md +143 -143
- package/skills/v8-utilities/references/platform-http-routes.md +83 -83
- package/skills/v8-utilities/references/server-api-index.md +188 -188
- package/skills/v8-workflow/SKILL.md +252 -252
- package/skills/v8-workflow/references/progressive-01-/350/212/202/347/202/271/345/274/200/345/247/213-v8-/344/272/213/344/273/266.md +180 -180
- package/skills/v8-workflow/references/workflow-configuration.md +49 -49
- package/skills/vision-engine/SKILL.md +160 -160
- package/skills/vision-engine/agents/openai.yaml +4 -4
- package/skills/vision-engine/references/architecture-and-acceptance.md +194 -194
- package/skills/workspace-conventions/SKILL.md +273 -273
- package/skills/workspace-conventions/references/progressive-01-/347/211/210/346/234/254/346/233/264/346/226/260/346/227/245/345/277/227/344/277/235/346/212/244/350/247/204/345/210/231-/345/274/272/345/210/266.md +209 -209
- package/skills/workspace-conventions/references/progressive-02-microi-net-api-/346/234/254/345/234/260/345/220/257/345/212/250/347/272/246/345/256/232.md +217 -217
- package/skills/workspace-conventions/references/progressive-03-cli-/344/270/216-ide-/346/217/222/344/273/266/351/224/231/347/211/210/345/205/261/345/255/230/347/272/246/345/256/232.md +27 -27
|
@@ -1,305 +1,305 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: v8-saas-multi-tenant
|
|
3
|
-
description: Microi V8 SaaS 多租户指南。用于处理租户隔离、主租户推广中心、按用户开通推广分享链接、匿名试用空库及 OsClient 三参数配置。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
> **Microi吾码基础规范(强制):** 任何 AI 模型与宿主每次新建或接续吾码任务,先完整读取 `../workspace-conventions/SKILL.md`,必须执行版本播报、`@microi.net/cli` 后台自动升级、Skills/MCP 同步和进度播报。安装与诊断读取 `../microi-codex-installer/SKILL.md`;更新失败延后重试,不阻断当前工作。
|
|
7
|
-
|
|
8
|
-
# Microi V8 SaaS 多租户引擎
|
|
9
|
-
|
|
10
|
-
你正在为 Microi 吾码平台编写多租户(SaaS)相关代码。每个租户使用独立数据库账号;Redis、对象存储、RabbitMQ、MQTT 和搜索集群可以共享基础设施,但必须使用租户命名空间与独立服务凭据,**所有 V8 代码都在租户上下文中运行**。
|
|
11
|
-
|
|
12
|
-
## 核心概念
|
|
13
|
-
|
|
14
|
-
Microi 多租户 = **`OsClient` + `OsClientType` + `OsClientNetwork`** 三参数模型:
|
|
15
|
-
|
|
16
|
-
| 参数 | 说明 | 示例 |
|
|
17
|
-
|------|------|------|
|
|
18
|
-
| `OsClient` | 租户标识(系统Key) | `tenant_a`, `tenant_demo` |
|
|
19
|
-
| `OsClientType` | 租户类型 | `Normal` / `App` / `Wechat` |
|
|
20
|
-
| `OsClientNetwork` | 网络环境 | `Intranet`(内网)/`Outernet`(外网) |
|
|
21
|
-
|
|
22
|
-
主租户不是固定字符串 `master`,而是由当前部署的环境变量 `OsClient` 或 `AppSettings:OsClient` 决定。租户记录存放在受保护的 `sys_osclients` 表中;普通业务角色和普通 V8 不得直接查询、复制或修改该表。
|
|
23
|
-
|
|
24
|
-
标准 MCP 连接必须保持 API 与这三个租户坐标一致。`MICROI_OS_CLIENT_TYPE`、`MICROI_OS_CLIENT_NETWORK` 是 MCP 进程的可选连接配置,显式设置时必须绑定非空 `MICROI_OS_CLIENT`;它们随 Login 表单、Refresh 正文、所有 API Header 和流式 multipart 表单传输,普通 JSON 业务正文与 GET 查询不额外注入 Type/Network。省略可选项保持原协议。SSE 对应 `X-Microi-OsClient`、`X-Microi-OsClientType`、`X-Microi-OsClientNetwork`,每个连接独立绑定身份;单次请求与已配置坐标冲突、重复或含非法标识时发送前拒绝。
|
|
25
|
-
|
|
26
|
-
连接或恢复后先执行 `initialize`、`tools/list`、`microi_get_status`,按服务端实际 API、OsClient、Type、Network 核验目标分区,再读基线或写入。Token 文件的四段键不能证明 HTTP 已选中该分区;不匹配时修复连接传输,不修改 SaaS 租户网络记录、跨分区借用身份或更换原业务请求键。
|
|
27
|
-
|
|
28
|
-
API 必须指向目标分区的真实节点。三参数 Header 只声明连接目标,不能切换节点可信运行分区或发布门禁;Header 已正确而 status 仍不匹配时停止写入并修正节点地址,禁止修改 SaaS/gate、借其它分区任务或用请求头强迫节点切区。
|
|
29
|
-
|
|
30
|
-
## 上下文变量
|
|
31
|
-
|
|
32
|
-
```javascript
|
|
33
|
-
V8.OsClient // 当前租户标识,如 'tenant_demo'
|
|
34
|
-
V8.OsClientType // 'Normal' / 'App' / 'Wechat'
|
|
35
|
-
V8.OsClientNetwork // 'Intranet' / 'Outernet'
|
|
36
|
-
V8.OsClientModel // 当前租户 SaaS 配置的脱敏副本
|
|
37
|
-
V8.ClientModel // OsClientModel 的兼容别名,同样是脱敏副本
|
|
38
|
-
V8.SysConfig // 当前租户系统配置根对象;不存在 PublicSettings 属性
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
前端 V8 的 `V8.SysConfig` 是匿名 `GetSysConfig` 的独立脱敏 `sys_config` 副本;`mci_system_setting` 的任何记录都不会进入浏览器。后端接口引擎与后端 V8 事件的 `V8.SysConfig` 包含当前租户完整、独立的 `sys_config`,后端私密设置统一位于 `V8.SysConfig.ServerPrivateSettings`,其中 Secret 由可信后端解密。两端都不存在 `PublicSettings` 包装层。后端可使用 Secret,但严禁返回前端、写日志或写审计。子租户显式传其它 `OsClient` 仍会被强制改回当前租户。
|
|
42
|
-
|
|
43
|
-
### V8.OsClientModel 常用字段
|
|
44
|
-
|
|
45
|
-
```javascript
|
|
46
|
-
V8.OsClientModel.SysTitle // 租户系统标题
|
|
47
|
-
V8.OsClientModel.DbType // 非敏感数据库类型
|
|
48
|
-
V8.OsClientModel.HDFS // 'Aliyun' / 'MinIO' / 'S3'
|
|
49
|
-
V8.OsClientModel.AliOssPublicDomain // 可公开的文件域名
|
|
50
|
-
// 当前租户自行扩展的业务字段只作存量兼容;新增公开配置使用 sys_config,后端私密参数使用 mci_system_setting
|
|
51
|
-
|
|
52
|
-
// 以下基础设施字段不会注入 V8:
|
|
53
|
-
// DbConn / DbReadConn / AuthSecret
|
|
54
|
-
// RedisHost / RedisPwd / MinIOSecretKey / AliOss*AccessKey*
|
|
55
|
-
// MQHost / MQUserName / MQPassword / MqttPwd / SearchEngineApiKey
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## 平台级配置与主租户规则
|
|
59
|
-
|
|
60
|
-
### 推广中心与匿名空库开通
|
|
61
|
-
|
|
62
|
-
- 主租户现有 `V8.FormEngine` 允许显式指定子租户;子租户被 `V8TenantContext.EnforceOsClient`
|
|
63
|
-
强制限制到自身。主租户业务员的业务范围须由接口引擎再次授权,不能仅凭主租户上下文放行全部租户。
|
|
64
|
-
- SaaS 官方应用唯一拥有三个 Managed Key:`platform-saas-promotion`、`platform-saas-public-trial`、
|
|
65
|
-
`platform-saas-public-trial-worker`。内置微服务的 `/saas-promotion` 归系统引擎,公开 `/saas-trial`
|
|
66
|
-
仅固定主租户、固定应用可匿名解析,禁止用 src/appKey/routePath 查询参数扩大匿名宿主范围。
|
|
67
|
-
- `V8.Method.AuthorizeSaasPromotion()` 仅绑定推广接口,重新读取有效账号、角色、菜单与管理角色。
|
|
68
|
-
默认业务员范围为 `ReferralUserId=当前sys_user.Id`;管理角色可读全局,平台管理员才可配置。
|
|
69
|
-
`V8.Method.ReadSaasTenantUsage({TenantIds,Refresh})` 只绑定同一接口,最多20个已授权子租户,无任意SQL或连接参数。
|
|
70
|
-
- 统计使用目标库主库固定聚合,缓存60秒、刷新至少15秒、并行最多4库。缺失或失败显示未知,
|
|
71
|
-
近7/30天登录用户与日期分布来自 `LastLoginTime`,不能声称获得历史登录次数。旧租户归属和期限为空
|
|
72
|
-
时保持未分配/未登记;试用结束不代替许可证,也不自动停库。
|
|
73
|
-
- `V8.Method.CreateSaasReferralCapability(linkId)` 只为授权推荐人或管理者签发绑定主租户与分区的链接票据。
|
|
74
|
-
- `V8.Method.ResumeSaasPublicTrialTask(taskId)` 仅供同一推广接口的原推荐人或授权管理者恢复失败申请。
|
|
75
|
-
保留原幂等键和加密数据库检查点,最多执行三次;不得重新分配已有数据库账号密码。
|
|
76
|
-
公开空库使用主租户提供的启动地址,`DomainName` 保持未绑定,不能把含下划线的租户标识拼成独立域名。
|
|
77
|
-
- 公开接口通过 `V8.Method.SaasPublicTrialAtom` 校验主配置、签名链接、推荐人、验证码和额度,冻结单向密码哈希
|
|
78
|
-
与受认证加密的限开通票据。Worker 设置 `StopHttp=1`,`V8.Method.ProvisionPublicSaasTrial` 验证固定Key、
|
|
79
|
-
持久任务身份与 fencing token,不接受伪造管理员。相同UUID和相同输入复用任务,不同输入拒绝。
|
|
80
|
-
DDL 前持久化加密账号检查点;强杀后恢复同一任务,已有账号必须使用检查点原凭据通过验证,禁止覆盖密码。
|
|
81
|
-
进度只用独立短期票据和安全结果投影,不能暴露连接、密码、任务正文或票据密钥。
|
|
82
|
-
- 公开开关与额度字段 `SaasPublicTrial*`、管理角色 `SaasPromotionManagerRoleIds` 仅当前主租户分区有效;
|
|
83
|
-
推荐Id、请求Id、完成检查点、试用期限、联系与跟进字段不得从主租户复制给子租户。
|
|
84
|
-
- `platform-saas-promotion-hook` 为 CreateIfMissing,仅 `BeforeCreateLink/Assign/UpdateFollowup` 脱敏事件。
|
|
85
|
-
不直接修改 Managed 接口保存个性化代码。更新 SaaS 应用和基础空库包两条链,并验证真实业务员、
|
|
86
|
-
管理员、匿名开库、同UUID重复提交、暂停后恢复及子租户越权,不以离线测试代替。
|
|
87
|
-
- 复用标准 MCP `microi_get_db_schema`、`microi_add_field`、`microi_create_table_index`、`microi_create_engine`、
|
|
88
|
-
`microi_save_engine_code`、`microi_create_module`、`microi_run_engine` 及应用源码/流式发布工具;
|
|
89
|
-
先完整回读、计划和dryRun,再按已授权范围写入。已有推广Hook采用CreateIfMissing,不覆盖。
|
|
90
|
-
|
|
91
|
-
#### 通过 AI + MCP 为指定用户开通推广链接
|
|
92
|
-
|
|
93
|
-
用户说“为某个业务员创建推广链接”时,使用现有接口完成配置和签发,不创建一次性维护引擎,也不直接改推广表。先通过 `profiles` 选择用户自己的主租户连接,执行 `microi_get_status` 核对节点、主租户及 Type/Network;普通用户的主租户不固定为官方 iTdos。
|
|
94
|
-
|
|
95
|
-
1. 用 `microi_get_engine_code` 完整读取 `platform-saas-promotion` 和 `platform-saas-public-trial`,有分页时拼齐并核对完整 SHA-256。再通过 `microi_run_engine` 执行 `{Action:'Bootstrap'}`,读取 `Actor/Users/Settings/Roles`,确认当前会话有创建权限。按准确 Account 或 Id 解析活跃推荐人;姓名重名时先澄清,禁止猜测用户 Id。管理员可以为活跃用户创建,业务员默认只为自己创建。
|
|
96
|
-
2. 执行 `{Action:'Links'}`,先查该推荐人的活动。已有符合请求且启用、未过期的链接可复用,保留其他活动与业务数据。只有平台管理员的 `Actor.CanConfigure=true` 才能配置公开开通。配置缺失且用户已授权启用时,通过 `SaveSettings` 写入真实主租户前端 HTTPS 地址;不要把 API 域名、临时测试端口或别人的平台地址当成 WebBase。仅创建链接不隐含修改已经设定的开通策略。
|
|
97
|
-
|
|
98
|
-
```javascript
|
|
99
|
-
// microi_run_engine:apiEngineKey='platform-saas-promotion'
|
|
100
|
-
// params 为下列对象;confirmExecution 使用同一 ApiEngineKey。
|
|
101
|
-
{ Action:'SaveSettings', Enabled:true, WebBase:'https://<主租户前端域名>',
|
|
102
|
-
TrialDays:14, DailyLimit:20, LinkLimit:50, ManagerRoleIds:[] }
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
上例为未配置时的默认值。已有试用天数、每日额度、单链接额度和管理角色应从 Bootstrap 回读并保留,除非用户明确要求调整;`ManagerRoleIds` 使用真实角色 Id 数组。保存后再次 Bootstrap 核对本分区配置。
|
|
106
|
-
3. 无合适活动时执行下列请求。`ReferralUserId` 必须来自第 1 步的权威用户目录;业务员额度和试用天数不能超过主租户设定值。
|
|
107
|
-
|
|
108
|
-
```javascript
|
|
109
|
-
{ Action:'CreateLink', Title:'<推广活动名称>', ReferralUserId:'<sys_user.Id>',
|
|
110
|
-
TrialDays:14, MaxTenants:50, ValidDays:30, Remark:'<可选活动说明>' }
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
创建超时先按推荐人、活动名称和时间回读 Links,确认是否已创建;禁止盲目重试导致重复活动。取得 `Data.Id` 后执行 `{Action:'ShareLink', Id:'<活动Id>'}`,返回 `Data.Url` 才是可分享地址。不要手拼 `ref=<用户Id>` 或将活动 Id 代替 `LinkToken`;票据绑定推荐人、活动、运行分区、到期时间和版本。切换链接启停状态会撤销旧地址,之后需重新签发。
|
|
114
|
-
4. 回读 Links 核对归属、启用状态、期限、试用天数和额度。在全新、未登录的浏览器 context 打开 `Data.Url`,核对匿名 `platform-saas-public-trial` 的 Bootstrap 成功、表单与图形验证码可用。验收链接不需要实际创建客户租户;只有明确授权开库后才提交真实申请,并按同一 RequestId 回读任务、租户归属和登录地址,保留幂等及精确清理证据。
|
|
115
|
-
|
|
116
|
-
最终交付可点击的分享地址、推荐人、试用天数、链接到期时间及额度,并区分“链接已可访问”和“客户租户已实际开通”。若接口不存在或平台版本不足,走官方 SaaS 应用与内置微服务更新,不通过临时 SQL 绕过鉴权。
|
|
117
|
-
|
|
118
|
-
制作空数据库时,角色、账号绑定和权限快照必须作为同一初始模板处理。只保留明确声明的初始角色,按权威角色重建保留账号的 `RoleIds` 与等级;删除业务角色及孤立菜单权限,清空包含源业务菜单的角色权限快照。初始角色缺失、删除或等级不符时停止制作,不得根据账号现有角色列表、角色名称或高等级推测哪些角色应保留。
|
|
119
|
-
|
|
120
|
-
组织数据属于同一空库模板边界:只保留明确声明的初始组织和部门,将保留账号的部门绑定与名称同步归一,并清理旧版账号关系表。保护这些平台表的物理结构,初始组织缺失或已删除时停止制作;验收必须在新租户查看真实组织树,不能只检查角色数量。清理只能作用于制作过程的隔离副本。
|
|
121
|
-
|
|
122
|
-
安装历史只有能对应保留平台应用的稳定身份才可继承:非空 `StoreId` 优先,旧记录没有该字段时再核对非空应用身份;不能凭名称或前缀保留孤立记录。SQL 预览、临时副本执行、公开空库文件更新与新租户登录验收是不同证据层;源主库和既有测试租户都不能作为清理执行目标。
|
|
123
|
-
|
|
124
|
-
主库 `sys_osclients` 保存租户数据库/Redis/存储路由及影响整个 API 进程的平台级配置;目标租户建立上下文后,`sys_config` 和 `mci_system_setting` 从该租户自己的数据库读取。平台级配置必须遵守“主租户为准、子租户只能降额隔离”的规则:
|
|
125
|
-
|
|
126
|
-
- 所有可变业务逻辑默认必须由接口引擎编排,包括但不限于租户开通、开库、初始化、归属修复、官网个人中心、付费额度等 SaaS 业务流程。C# 后端只暴露原子 V8 能力,例如建库、导入空库模板、复制 `sys_config`、刷新 SaaS 缓存、补偿回滚、字段兜底等;不要把可变业务分支写死到 Controller 或 `TenantProvisioningService` 这类后端定制代码里。接口引擎缺少能力时,优先扩展 `V8.Method`/V8 引擎原子函数,再由接口引擎调用。
|
|
127
|
-
- 官方租户开通固定由 SaaS 包的 `platform-create-tenant` 编排:`platform-runtime-custom-hook` 的 Before 阶段可以阻断,`AuthorizeCurrentUserTenantProvisioning` / `ProvisionCurrentUserTenant` 只从可信主租户 DiyToken 派生所有者与密码材料;创建完成后的 Hook/审计失败只能返回 Warning,不能诱导重复创建。系统账号偏好/资料与租户系统设置分别由 `app.microi.sys_user`、`app.microi.sys-config` 单一拥有,SaaS/Store 不得复制这些 Managed ApiEngineKey。
|
|
128
|
-
- 租户开库失败时,先核对编排 `OsClientDbConn` 的真实账号与权限。业务库账号通常不能开库、创建用户或授权;应使用已有正确授权的管理账号更新编排,不通过 SQL/MCP 手工修复业务数据库。管理员页面必须同时显示中文原因、失败阶段、可执行的处理方法,以及可展开且已脱敏的原始异常链;区分密码/来源认证失败与数据库权限不足,不能只显示笼统失败或隐藏驱动原始错误。
|
|
129
|
-
- 旧版 UniApp 的 `microi-init` 是 SaaS 包继续托管的 Managed 兼容门面。匿名阶段只组合 `platform-os-client-by-domain` 与 `platform-sys-config` 的公开投影;原始 DiyToken 必须由 `GetCurrentToken` 和 `RefreshLoginUser(..., rawToken)` 在后端重新验证且绑定当前租户,菜单再由只允许该固定 Key 调用的 `GetLegacyInitMenuTree(rawToken, osClient?)` 复用 `SysMenuLogic` 权威角色过滤。禁止在匿名 V8 中直接通过 FormEngine 读取 `sys_menu`;域名解析到其它租户时返回目标 `OsClient` 并要求重试,禁止匿名跨租户读取配置或菜单。
|
|
130
|
-
- 主租户由运行环境决定:优先读取环境变量 `OsClient`,其次读取 `appsettings.json` 的 `AppSettings:OsClient`。只有这条主租户 `sys_osclients` 数据中的平台级字段会作为全局配置生效。
|
|
131
|
-
- 同一个主租户可以同时运行在 `Product/Internal`、`Product/Internet` 等多个分区;租户目录、后台任务领取、通知和批量平台应用维护都必须按当前节点的 `OsClientType + OsClientNetwork` 隔离。一次全量维护只证明当前分区,事故恢复必须先盘点所有活跃分区,再从各分区对应节点分别执行并等待 `SucceededCount=ExpectedCount、FailedCount=0`,随后各自以新幂等键做零安装/零更新复跑。禁止临时改租户网络字段、跨分区借用任务或并发维护可能指向同一物理库的重复租户记录。
|
|
132
|
-
- 大范围启动事故只允许受信后台编排器使用 `MaintenanceScope=StartupDependencies`,精确闭包固定为 `app.microi.store + app.microi.saas-engine`,并可显式启用 `StartupDependencyBootstrapOnly=true`。编排器必须先用权威当前分区目录校验 `TargetOsClients`,再在子任务仍为 `Pending` 时原子写入并强回读两应用范围与只自举标志;失败即取消,禁止退化为完整安装。工作器只从官方不可变包补齐 `platform-sys-menu` 和六项 SaaS 启动门面,七项物理契约强回读通过后终止,不写安装版本。该模式只恢复可登录性,不代表 API 进程的完整运行时已经就绪;新版后端接收流量前还必须从九个内置官方基础应用包补齐并回读全部接口引擎,后续完整应用更新仍走普通商城任务。未带标志的任务行为不得改变。
|
|
133
|
-
- API 启动配置只有十项白名单:`OsClient`、`OsClientType`、`OsClientNetwork`、`OsClientDbType`、`OsClientDbConn`、`OsClientRedisHost`、`OsClientRedisPort`、`OsClientRedisPwd`、`OsClientRedisDataBase`、`OsClientDbMongoConn`。除这十项外,部署/节点级运行参数与基础设施秘密从主控 `sys_osclients` 读取;允许子租户自行维护且需要浏览器判断的业务开关、入口显示和公开交互配置使用该租户 `sys_config` 实体字段,OAuth/第三方集成的凭据、RP/Origin/Issuer/Scope 与仅后端参数使用 `mci_system_setting`,未配置时使用代码安全默认值。官方 License 恢复次数/间隔与固定私钥挂载 `/app/microi_private.pem` 是信任链例外。禁止再增加 `MICROI_*`、`DOS_ORM_*`、自定义 `AppSettings` 节点或动态名称的环境变量读取。节点身份由平台自动生成。
|
|
134
|
-
- 存量畅捷通/微信 OAuth C# 协议网关有一组已发布到 SaaS 引擎的兼容字段:`OAuthReturnUrlOrigins`、`ChanjetOAuthState`、`ChanjetAesKey`、`ChanjetAppKey`、`WeChatTemplateAppId`、`WeChatTemplateAppSecret`、`WeChatTemplateId`、`WeChatMiniProgramAppId`。只能通过 Core 的租户绑定协议设置原子按请求权威 `OsClient` 读取,禁止使用主租户 `ConfigHelper` RuntimeConfigurationReader;整组字段不得复制给新租户,其中 OAuthState/AES Key/AppKey/AppSecret 不得进入 `V8.OsClientModel` 或前端投影且必须在审计中掩码。新集成不得继续扩展该兼容集合,仍使用当前租户 `mci_system_setting` + Managed ApiEngine。
|
|
135
|
-
- `ASPNETCORE_*`、`DOTNET_*` 仅用于 .NET 宿主;构建、安装、测试、MCP、发布脚本可使用自身进程变量,但 API 生产代码不得把它们当业务配置。新增 SaaS 运行字段必须配套独立或既有 Tab、幂等升级、缓存刷新、敏感字段脱敏、子租户不继承和源码扫描测试。
|
|
136
|
-
- 文件上传的租户业务开关与额度按“当前租户 `sys_osclients` → 代码默认值”解析;现行负向字段 `DisableFileUpload` 默认关闭/空值即允许上传,只有 `1/true` 才禁止。旧 `FileUploadEnabled` 只在新物理字段尚不存在的滚动升级节点回退读取,并须在新版 SaaS 表单隐藏。平台固定灾难保护、HTTP/Multipart/Form 和反向代理上限不可由租户覆盖,也不要求安装者维护额外上传环境变量。
|
|
137
|
-
- 类似 MQTT 端口、PressureGuard、V8Limits、OrmLimits、StartupLimits、SecurityGuard 这类影响整进程资源的配置,不能让每个子租户各自抬高全局上限。子租户同名隔离字段只能降低自己的并发、等待时间或资源额度,用于隔离弱租户、试用租户或异常租户。
|
|
138
|
-
- 修改 `sys_osclients` 的表、字段、数据源或配置值后,必须刷新 SaaS 引擎运行缓存,并回读验证字段 `Component`、`Data`、`Config`、实际数据值和前端真实消费结果。不要只看 MCP 写入成功。
|
|
139
|
-
- SaaS 配置只在启动、管理员保存 `sys_osclients` 或显式租户刷新时发布到共享 Redis。初始化数据库会话、创建 `V8.Dbs` 运行态对象、普通 FormEngine 请求和表单设计器保存不得冒充配置变更反复发布。
|
|
140
|
-
- JWT Key 由可信后端生成并持久化;SaaS 表单只读显示配置状态,不允许普通表单或 V8 写入 `AuthSecret`。手动接入旧库的 NULL/空白值必须支持原子写回,多节点竞争后回读持久胜者;重复刷新不能轮换有效 Key。只读状态查询不得初始化目标租户数据库。验收只记录是否已配置、是否稳定,不输出密钥原文。
|
|
141
|
-
- 扩展库缓存必须区分“尚未加载”和“已加载但为 0 条”;后者是有效结果。没有配置 `microi_database` 的租户不能在每次 V8 执行时重复查询、调用 `AddOrUptClient` 或打印“缓存 OsClient 配置到 Redis”。
|
|
142
|
-
- 多节点的缓存失效订阅只做本节点失效与数据库回源,禁止收到消息后再次发布形成回声。进程内初始化标记仅是可丢失优化,真正租户配置仍以共享数据库/Redis 为准。
|
|
143
|
-
- 新增平台级字段时,字段名建议保持英文稳定,例如 `PressureGlobalMaxConcurrentRequests`、`PressureV8MaxConcurrentExecutions`、`PressureOrmMaxConcurrentConnectionOpens`;字段标签和说明必须中文,说明中写清楚“主租户有效/子租户仅可降低”。
|
|
144
|
-
- 新租户记录不得复制主租户的数据库、鉴权、Redis/对象存储密钥或 MQ/MQTT/Search 凭据。共享基础设施地址与管理密钥只在服务端运行时解析,不持久化到子租户记录,也不进入 V8 投影。
|
|
145
|
-
- RabbitMQ 子租户必须使用独立 user/vhost/ACL,MQTT 必须使用独立账号密码,Search 必须使用限制到 `{osClient}_*` 的 API Key/用户。外部资源尚未真实创建时保持空凭据并失败关闭,禁止把主租户管理员凭据复制过去冒充完成。
|
|
146
|
-
- `V8.Cache`、`V8.HDFS`、RabbitMQ、MQTT、Search 分别强制 `Microi:{OsClient}:*`、`/{osClient}/...`、`microi.{osClient}.*`、`tenant/{osClient}/...`、`{osClient}_*` 命名空间。body/query 中的 `OsClient` 不能覆盖登录 Token 或 V8 上下文。
|
|
147
|
-
|
|
148
|
-
## 接口调用区分租户的三种方式
|
|
149
|
-
|
|
150
|
-
### 方式 1:Token 自动识别(最常用)
|
|
151
|
-
|
|
152
|
-
请求头携带 `Token`,平台自动识别用户所属租户。
|
|
153
|
-
|
|
154
|
-
```bash
|
|
155
|
-
GET /apiengine/get-products
|
|
156
|
-
Token: xxx-token-xxx
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### 方式 2:URL 参数
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
GET /apiengine/get-products?OsClient=tenant_demo
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### 方式 3:特殊 URL 格式(无 Token、无参数)
|
|
166
|
-
|
|
167
|
-
```bash
|
|
168
|
-
GET /apiengine/get-products--OsClient--tenant_demo--
|
|
169
|
-
GET /apiengine/get-products--OsClient--tenant_demo--OsClientType--App--
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
> 适用于第三方回调(无法添加 Header)、支付/微信回调等场景。
|
|
173
|
-
|
|
174
|
-
## 跨租户操作(仅可信控制面)
|
|
175
|
-
|
|
176
|
-
普通 V8 的 `FormEngine`、`DataSourceEngine`、`TranslateEngine`、`WFEngine`、`Cache`、`HDFS`、MQ/MQTT、Search 和 `Dbs` 都必须绑定当前 Token/V8 上下文中的 `OsClient`。请求 body/query 里传入其它租户不能切换连接,也不能读取其它租户凭据。
|
|
177
|
-
|
|
178
|
-
租户开通、迁移、备份或平台管理员代维只能走明确的控制面服务/接口引擎:
|
|
179
|
-
|
|
180
|
-
- 调用者必须是 `Level >= 9999`,并再次校验目标租户白名单和操作类型;
|
|
181
|
-
- 使用专用原子能力,不通过通用 FormEngine 读取完整 `sys_osclients` 记录;
|
|
182
|
-
- 不把数据库、认证、Redis、存储、MQ/MQTT、搜索等连接与密钥投影进 V8;
|
|
183
|
-
- 每次操作写安全审计、幂等键和补偿状态,并对目标租户回读验收;
|
|
184
|
-
- 多节点部署使用共享租约和业务幂等,不能依赖进程静态锁。
|
|
185
|
-
|
|
186
|
-
### SaaS 数据库 ZIP 开库的进度与租约
|
|
187
|
-
|
|
188
|
-
通过 SaaS 引擎上传数据库 ZIP 创建租户时,必须把上传和还原建模为两个独立阶段:
|
|
189
|
-
|
|
190
|
-
- 上传使用分片会话并显示真实字节进度;暂停或网络中断后复用同一文件指纹续传,不能把上传百分比冒充数据库导入进度。
|
|
191
|
-
- 上传完成后提交平台持久后台任务。租户开通进度总数使用后端共享契约的固定 13 步,接口引擎、可信宿主原子和前端不得各自维护不同分母。
|
|
192
|
-
- 第 2 步是数据库 ZIP 校验与还原。该阶段应按真实 SQL 读取量推进总百分比,并显示已读取/总字节、SQL 百分比、已执行语句数、当前批次与语句类型、平均吞吐和动态预计剩余时间;不能长时间只显示静态的 `2 / 13`。
|
|
193
|
-
- 进度状态仅在距上次更新约 2 秒或新增约 16MB 数据时刷新;执行日志只记录阶段里程碑和 SQL 每跨过约 5% 的进度,前端只渲染最近 200 条。禁止按 SQL 行或每条语句推送日志,避免几十万条数据把共享任务表、SignalR 或浏览器 DOM 拖垮。
|
|
194
|
-
- 页面同时显示服务端心跳。单个百分比短时不变不等于卡死,应综合心跳、字节、语句数、批次和消息判断;失败、取消或中断必须保留最后真实进度和错误原因,只有成功终态才算开库完成。
|
|
195
|
-
|
|
196
|
-
租户开库使用平台可信后台上下文中的可续租共享锁:`Timeout` 是单次 Redis 租期,当前开库最长保护边界为 12 小时。普通 HTTP/V8 请求传入 `_BackgroundTaskId`、`_TrustedServerInvocation` 或伪造用户对象不能开启续租。持有者令牌不匹配、锁过期、Redis 所有权/续租确认失败或达到最长租约都必须失败关闭并停止推进;不能为了避免报错而把真实锁丢失降级成成功或 Warning。
|
|
197
|
-
|
|
198
|
-
自动续租只解决“正常长任务不因短 TTL 自然过期”,不能代替业务幂等、检查点、补偿状态和 fencing token。大库导入完成但域名绑定未完成时,应保留已经成功创建的租户和数据库,进入明确的域名补偿状态;不能因数据面域名失败重新导入整个数据库。接口引擎的通用锁配置读取 `../v8-api-config/SKILL.md`,长任务按钮和检查点读取 `../v8-menu-buttons/references/progressive-02-8-模式-f-后台任务按钮-长任务.md`。
|
|
199
|
-
|
|
200
|
-
## 缓存按租户隔离
|
|
201
|
-
|
|
202
|
-
```javascript
|
|
203
|
-
// 推荐传逻辑 Key;服务端自动添加当前租户前缀
|
|
204
|
-
var key = 'Product:' + V8.Param.id;
|
|
205
|
-
V8.Cache.Set(key, value, 600);
|
|
206
|
-
|
|
207
|
-
// 完整当前租户 Key 继续兼容
|
|
208
|
-
var fullKey = 'Microi:' + V8.OsClient + ':Product:' + V8.Param.id;
|
|
209
|
-
|
|
210
|
-
// 其它租户的 Microi: 前缀会被服务端拒绝
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
## 接口引擎中针对不同租户走不同逻辑
|
|
214
|
-
|
|
215
|
-
```javascript
|
|
216
|
-
// 租户差异应来自当前租户的非敏感业务配置,不要硬编码某个“主租户”字符串
|
|
217
|
-
if (V8.OsClientModel.OrderApprovalMode === 'Direct') {
|
|
218
|
-
V8.FormEngine.UptFormData('Order', { Id: id, Status: 'Approved' });
|
|
219
|
-
} else {
|
|
220
|
-
await V8.WFEngine.StartWork({ FlowDesignId: 'order-flow', TableRowId: id });
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// App 端 vs PC 端不同返回
|
|
224
|
-
if (V8.OsClientType === 'App') {
|
|
225
|
-
return { Code: 1, Data: simplifiedList };
|
|
226
|
-
}
|
|
227
|
-
return { Code: 1, Data: fullList };
|
|
228
|
-
|
|
229
|
-
// 内网外网走不同 ERP 网关
|
|
230
|
-
var erpUrl = (V8.OsClientNetwork === 'Intranet')
|
|
231
|
-
? 'http://192.168.1.10/erp/api'
|
|
232
|
-
: 'https://erp.public.com/api';
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
## 第三方密钥放租户动态设置(不要硬编码)
|
|
236
|
-
|
|
237
|
-
```javascript
|
|
238
|
-
// ❌ 危险:密钥写在代码里,所有租户共用,无法独立轮换
|
|
239
|
-
var ak = 'AKIDxxxxxxxx';
|
|
240
|
-
|
|
241
|
-
// ✅ 浏览器需要判断的开关:使用 sys_config 实体字段
|
|
242
|
-
var giteeEnabled = V8.SysConfig.GiteeLoginEnabled === 1;
|
|
243
|
-
|
|
244
|
-
// ✅ 后端 V8 可读取当前租户 Secret 并直接调用供应商
|
|
245
|
-
var privateSettings = V8.SysConfig.ServerPrivateSettings || {};
|
|
246
|
-
var secret = privateSettings['Login.Gitee.ClientSecret'];
|
|
247
|
-
// 禁止 return secret、console.log(secret) 或写入前端可读字段。
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
> `mci_system_setting` 位于每个租户自己的数据库,只保存不能公开或仅供后端执行的配置;普通值与 Secret 都不会下发浏览器。Secret 保存认证密文,只在后端 V8 的当前租户 `ServerPrivateSettings` 中解密使用。能力开关和入口显示必须建成 `sys_config` 实体字段,禁止通过 `IsPublic` 或其它运行时勾选把私密记录公开。前端 V8、普通 FormEngine HTTP、匿名/访问密钥会话不能读取私密设置,后端 V8 也不能获得通用解密器。`sys_osclients` 自定义业务字段只保留存量兼容;共享基础设施字段由服务端强制移除,不能用自定义同义字段绕过安全代理。
|
|
251
|
-
|
|
252
|
-
## 用户扩展字段访问(同理)
|
|
253
|
-
|
|
254
|
-
平台 `sys_user` 也由表单引擎驱动。如给 `sys_user` 添加 `Wife` 字段:
|
|
255
|
-
|
|
256
|
-
```javascript
|
|
257
|
-
// V8 代码中可访问
|
|
258
|
-
V8.CurrentUser.Wife;
|
|
259
|
-
|
|
260
|
-
// SQL 数据源中可访问
|
|
261
|
-
SELECT * FROM Contact WHERE OwnerId = $CurrentUser.Id$ AND Spouse = $CurrentUser.Wife$
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
## 常见错误
|
|
265
|
-
|
|
266
|
-
- 旧库升级的内置应用包包含定时任务时,升级内核按“资源独立提交 → 幂等保存并回读 Quartz/任务元数据 → 确认安装版本”执行。仅程序集白名单包及不可伪造的宿主授权可进入该兼容流程;普通应用安装仍必须使用持久后台任务分片。任一阶段失败不推进 ServerVersion,修复后从原升级入口重试,不手动抬高版本或伪造任务信封。
|
|
267
|
-
|
|
268
|
-
❌ 绕开 `V8.Cache` 使用底层 Redis → 租户数据串号(V8 已不再暴露底层句柄)
|
|
269
|
-
❌ MongoDB DbName 不带 OsClient → 数据混淆
|
|
270
|
-
❌ 把 OsClientModel 字段直接返回给前端 → 密钥泄漏
|
|
271
|
-
❌ 查询 `mci_system_setting.SecretCipher` 或给 V8 暴露通用解密器 → 密钥边界失效
|
|
272
|
-
❌ 在前端硬编码 OsClient → 一改全改,应通过 token/URL 自动识别
|
|
273
|
-
❌ 跨租户操作不验证当前用户权限 → 越权风险
|
|
274
|
-
❌ 子租户缺少 MQ/MQTT/Search 独立凭据时回退主账号 → 全平台越权
|
|
275
|
-
|
|
276
|
-
## 检查清单
|
|
277
|
-
|
|
278
|
-
- 子租户授权使用官方 SaaS 应用的 `sys_osclients.LicenseProductType` 与 `LicenseExpirationDate`(UTC)字段;两项留空继承主授权。只允许主租户超级管理员设置,不能超过已验签主授权的版本和日期;运行时再次裁剪。两项不得通过主配置合并自动复制到子租户。不要在可编辑 V8 里代替可信授权边界。
|
|
279
|
-
- 授权到期文案和提前天数在消息通知页设置。官方与主租户策略分别触发,不能因官方已触发或未触发而跳过主租户检查。签发帐号 `sys_user.LicenseExpirationDate` 未设置表示永久有效,但可签发版本及请求日期仍需校验。
|
|
280
|
-
|
|
281
|
-
- [ ] 缓存只通过 `V8.Cache` 使用逻辑 Key 或当前租户完整 Key
|
|
282
|
-
- [ ] 所有 MongoDB DbName 都包含 `V8.OsClient`
|
|
283
|
-
- [ ] 当前租户自有的业务集成密钥可放 `V8.OsClientModel`,共享 Redis/存储/MQ/MQTT/Search 凭据只能由服务端托管
|
|
284
|
-
- [ ] 跨租户操作前校验权限
|
|
285
|
-
- [ ] 不向前端返回 `V8.OsClientModel`
|
|
286
|
-
- [ ] 子租户数据库账号只授权本租户库,MQ/MQTT/Search 独立凭据已真实创建
|
|
287
|
-
- [ ] 文件、队列、Topic、索引均由服务端规范为当前租户命名空间
|
|
288
|
-
- [ ] 无扩展库租户重复执行 V8 时不会重复刷新 SaaS 配置;真实 `sys_osclients` 保存后各节点能按租户失效并回源
|
|
289
|
-
- [ ] ZIP 开库区分上传与还原进度,使用固定 13 步、低频明细、服务端心跳和有界日志
|
|
290
|
-
- [ ] 开库锁只由可信持久后台任务自动续租;真实租约丢失失败关闭,所有副作用仍具备幂等、检查点和 fencing token
|
|
291
|
-
|
|
292
|
-
## Microi.AI 中转站租户凭据
|
|
293
|
-
|
|
294
|
-
- `mic_ai` 的 `Microi.AI中转站.ApiKey` 是租户调用吾码官方中转站的用户凭据。运行时不得因为该字段为空而静默创建、回退到当前用户字段或绕过校验,否则管理员无法判断真实配置来源。
|
|
295
|
-
- 老租户由用户在吾码官网个人中心复制 ApiKey 后填写到本租户的 `mic_ai` 中转站记录;空值应返回明确配置错误。
|
|
296
|
-
- 官网创建新 SaaS 租户时,必须先取得当前官网账号的 ApiKey,再由租户初始化服务写入新库 `mic_ai` 的 `Microi.AI中转站` 记录。该自动写入只发生在受控开库流程,不得散落到普通 AI 对话请求中。
|
|
297
|
-
- 开库入口把 ApiKey 传给后台 worker 后,worker 还必须继续显式传入最终的原子初始化方法;不能只在父接口或中间参数中“带过”。每个异步/后台边界都应对空值立即失败,避免租户创建成功但 `mic_ai.ApiKey` 静默为空。
|
|
298
|
-
- 自动化验收必须通过新租户 `admin` 登录回读 `mic_ai`,只输出“非空、长度、与官网账号 ApiKey 是否一致”等布尔结果,不得把真实 ApiKey 写入日志、截图或测试报告。
|
|
299
|
-
- 中转模型公开目录只返回模型 Id、显示名、厂商等非敏感字段,可匿名读取;严禁把官方上游模型的 ApiKey、Endpoint 私密配置随模型列表返回前端。
|
|
300
|
-
|
|
301
|
-
### 旧结构空库制作验收
|
|
302
|
-
|
|
303
|
-
空库脱敏生成器应只读实际物理列;组织机构旧表缺少可选父级名称列时,只写已有父级 Id,不为制作模板修改主库结构。物理字段发现失败应在输出清理 SQL 前失败关闭。验收同时覆盖有该列、缺少该列及读取失败,最终检查隔离副本和官方空库下载包。
|
|
304
|
-
|
|
305
|
-
应用文件与版本清理不得在 MySQL 5.7 的 DELETE 外连接中用 `Id = AppId OR AppKey = AppId`。先在隔离副本内物化带主键的 Id/AppKey 保留集合,分别覆盖当前商城 Id、历史 AppKey、业务应用、孤立记录与 NULL;验证新旧结果一致,源主库只读。真实 SQL 耗时与 Node 生成器测试需分别记录。
|
|
1
|
+
---
|
|
2
|
+
name: v8-saas-multi-tenant
|
|
3
|
+
description: Microi V8 SaaS 多租户指南。用于处理租户隔离、主租户推广中心、按用户开通推广分享链接、匿名试用空库及 OsClient 三参数配置。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> **Microi吾码基础规范(强制):** 任何 AI 模型与宿主每次新建或接续吾码任务,先完整读取 `../workspace-conventions/SKILL.md`,必须执行版本播报、`@microi.net/cli` 后台自动升级、Skills/MCP 同步和进度播报。安装与诊断读取 `../microi-codex-installer/SKILL.md`;更新失败延后重试,不阻断当前工作。
|
|
7
|
+
|
|
8
|
+
# Microi V8 SaaS 多租户引擎
|
|
9
|
+
|
|
10
|
+
你正在为 Microi 吾码平台编写多租户(SaaS)相关代码。每个租户使用独立数据库账号;Redis、对象存储、RabbitMQ、MQTT 和搜索集群可以共享基础设施,但必须使用租户命名空间与独立服务凭据,**所有 V8 代码都在租户上下文中运行**。
|
|
11
|
+
|
|
12
|
+
## 核心概念
|
|
13
|
+
|
|
14
|
+
Microi 多租户 = **`OsClient` + `OsClientType` + `OsClientNetwork`** 三参数模型:
|
|
15
|
+
|
|
16
|
+
| 参数 | 说明 | 示例 |
|
|
17
|
+
|------|------|------|
|
|
18
|
+
| `OsClient` | 租户标识(系统Key) | `tenant_a`, `tenant_demo` |
|
|
19
|
+
| `OsClientType` | 租户类型 | `Normal` / `App` / `Wechat` |
|
|
20
|
+
| `OsClientNetwork` | 网络环境 | `Intranet`(内网)/`Outernet`(外网) |
|
|
21
|
+
|
|
22
|
+
主租户不是固定字符串 `master`,而是由当前部署的环境变量 `OsClient` 或 `AppSettings:OsClient` 决定。租户记录存放在受保护的 `sys_osclients` 表中;普通业务角色和普通 V8 不得直接查询、复制或修改该表。
|
|
23
|
+
|
|
24
|
+
标准 MCP 连接必须保持 API 与这三个租户坐标一致。`MICROI_OS_CLIENT_TYPE`、`MICROI_OS_CLIENT_NETWORK` 是 MCP 进程的可选连接配置,显式设置时必须绑定非空 `MICROI_OS_CLIENT`;它们随 Login 表单、Refresh 正文、所有 API Header 和流式 multipart 表单传输,普通 JSON 业务正文与 GET 查询不额外注入 Type/Network。省略可选项保持原协议。SSE 对应 `X-Microi-OsClient`、`X-Microi-OsClientType`、`X-Microi-OsClientNetwork`,每个连接独立绑定身份;单次请求与已配置坐标冲突、重复或含非法标识时发送前拒绝。
|
|
25
|
+
|
|
26
|
+
连接或恢复后先执行 `initialize`、`tools/list`、`microi_get_status`,按服务端实际 API、OsClient、Type、Network 核验目标分区,再读基线或写入。Token 文件的四段键不能证明 HTTP 已选中该分区;不匹配时修复连接传输,不修改 SaaS 租户网络记录、跨分区借用身份或更换原业务请求键。
|
|
27
|
+
|
|
28
|
+
API 必须指向目标分区的真实节点。三参数 Header 只声明连接目标,不能切换节点可信运行分区或发布门禁;Header 已正确而 status 仍不匹配时停止写入并修正节点地址,禁止修改 SaaS/gate、借其它分区任务或用请求头强迫节点切区。
|
|
29
|
+
|
|
30
|
+
## 上下文变量
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
V8.OsClient // 当前租户标识,如 'tenant_demo'
|
|
34
|
+
V8.OsClientType // 'Normal' / 'App' / 'Wechat'
|
|
35
|
+
V8.OsClientNetwork // 'Intranet' / 'Outernet'
|
|
36
|
+
V8.OsClientModel // 当前租户 SaaS 配置的脱敏副本
|
|
37
|
+
V8.ClientModel // OsClientModel 的兼容别名,同样是脱敏副本
|
|
38
|
+
V8.SysConfig // 当前租户系统配置根对象;不存在 PublicSettings 属性
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
前端 V8 的 `V8.SysConfig` 是匿名 `GetSysConfig` 的独立脱敏 `sys_config` 副本;`mci_system_setting` 的任何记录都不会进入浏览器。后端接口引擎与后端 V8 事件的 `V8.SysConfig` 包含当前租户完整、独立的 `sys_config`,后端私密设置统一位于 `V8.SysConfig.ServerPrivateSettings`,其中 Secret 由可信后端解密。两端都不存在 `PublicSettings` 包装层。后端可使用 Secret,但严禁返回前端、写日志或写审计。子租户显式传其它 `OsClient` 仍会被强制改回当前租户。
|
|
42
|
+
|
|
43
|
+
### V8.OsClientModel 常用字段
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
V8.OsClientModel.SysTitle // 租户系统标题
|
|
47
|
+
V8.OsClientModel.DbType // 非敏感数据库类型
|
|
48
|
+
V8.OsClientModel.HDFS // 'Aliyun' / 'MinIO' / 'S3'
|
|
49
|
+
V8.OsClientModel.AliOssPublicDomain // 可公开的文件域名
|
|
50
|
+
// 当前租户自行扩展的业务字段只作存量兼容;新增公开配置使用 sys_config,后端私密参数使用 mci_system_setting
|
|
51
|
+
|
|
52
|
+
// 以下基础设施字段不会注入 V8:
|
|
53
|
+
// DbConn / DbReadConn / AuthSecret
|
|
54
|
+
// RedisHost / RedisPwd / MinIOSecretKey / AliOss*AccessKey*
|
|
55
|
+
// MQHost / MQUserName / MQPassword / MqttPwd / SearchEngineApiKey
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 平台级配置与主租户规则
|
|
59
|
+
|
|
60
|
+
### 推广中心与匿名空库开通
|
|
61
|
+
|
|
62
|
+
- 主租户现有 `V8.FormEngine` 允许显式指定子租户;子租户被 `V8TenantContext.EnforceOsClient`
|
|
63
|
+
强制限制到自身。主租户业务员的业务范围须由接口引擎再次授权,不能仅凭主租户上下文放行全部租户。
|
|
64
|
+
- SaaS 官方应用唯一拥有三个 Managed Key:`platform-saas-promotion`、`platform-saas-public-trial`、
|
|
65
|
+
`platform-saas-public-trial-worker`。内置微服务的 `/saas-promotion` 归系统引擎,公开 `/saas-trial`
|
|
66
|
+
仅固定主租户、固定应用可匿名解析,禁止用 src/appKey/routePath 查询参数扩大匿名宿主范围。
|
|
67
|
+
- `V8.Method.AuthorizeSaasPromotion()` 仅绑定推广接口,重新读取有效账号、角色、菜单与管理角色。
|
|
68
|
+
默认业务员范围为 `ReferralUserId=当前sys_user.Id`;管理角色可读全局,平台管理员才可配置。
|
|
69
|
+
`V8.Method.ReadSaasTenantUsage({TenantIds,Refresh})` 只绑定同一接口,最多20个已授权子租户,无任意SQL或连接参数。
|
|
70
|
+
- 统计使用目标库主库固定聚合,缓存60秒、刷新至少15秒、并行最多4库。缺失或失败显示未知,
|
|
71
|
+
近7/30天登录用户与日期分布来自 `LastLoginTime`,不能声称获得历史登录次数。旧租户归属和期限为空
|
|
72
|
+
时保持未分配/未登记;试用结束不代替许可证,也不自动停库。
|
|
73
|
+
- `V8.Method.CreateSaasReferralCapability(linkId)` 只为授权推荐人或管理者签发绑定主租户与分区的链接票据。
|
|
74
|
+
- `V8.Method.ResumeSaasPublicTrialTask(taskId)` 仅供同一推广接口的原推荐人或授权管理者恢复失败申请。
|
|
75
|
+
保留原幂等键和加密数据库检查点,最多执行三次;不得重新分配已有数据库账号密码。
|
|
76
|
+
公开空库使用主租户提供的启动地址,`DomainName` 保持未绑定,不能把含下划线的租户标识拼成独立域名。
|
|
77
|
+
- 公开接口通过 `V8.Method.SaasPublicTrialAtom` 校验主配置、签名链接、推荐人、验证码和额度,冻结单向密码哈希
|
|
78
|
+
与受认证加密的限开通票据。Worker 设置 `StopHttp=1`,`V8.Method.ProvisionPublicSaasTrial` 验证固定Key、
|
|
79
|
+
持久任务身份与 fencing token,不接受伪造管理员。相同UUID和相同输入复用任务,不同输入拒绝。
|
|
80
|
+
DDL 前持久化加密账号检查点;强杀后恢复同一任务,已有账号必须使用检查点原凭据通过验证,禁止覆盖密码。
|
|
81
|
+
进度只用独立短期票据和安全结果投影,不能暴露连接、密码、任务正文或票据密钥。
|
|
82
|
+
- 公开开关与额度字段 `SaasPublicTrial*`、管理角色 `SaasPromotionManagerRoleIds` 仅当前主租户分区有效;
|
|
83
|
+
推荐Id、请求Id、完成检查点、试用期限、联系与跟进字段不得从主租户复制给子租户。
|
|
84
|
+
- `platform-saas-promotion-hook` 为 CreateIfMissing,仅 `BeforeCreateLink/Assign/UpdateFollowup` 脱敏事件。
|
|
85
|
+
不直接修改 Managed 接口保存个性化代码。更新 SaaS 应用和基础空库包两条链,并验证真实业务员、
|
|
86
|
+
管理员、匿名开库、同UUID重复提交、暂停后恢复及子租户越权,不以离线测试代替。
|
|
87
|
+
- 复用标准 MCP `microi_get_db_schema`、`microi_add_field`、`microi_create_table_index`、`microi_create_engine`、
|
|
88
|
+
`microi_save_engine_code`、`microi_create_module`、`microi_run_engine` 及应用源码/流式发布工具;
|
|
89
|
+
先完整回读、计划和dryRun,再按已授权范围写入。已有推广Hook采用CreateIfMissing,不覆盖。
|
|
90
|
+
|
|
91
|
+
#### 通过 AI + MCP 为指定用户开通推广链接
|
|
92
|
+
|
|
93
|
+
用户说“为某个业务员创建推广链接”时,使用现有接口完成配置和签发,不创建一次性维护引擎,也不直接改推广表。先通过 `profiles` 选择用户自己的主租户连接,执行 `microi_get_status` 核对节点、主租户及 Type/Network;普通用户的主租户不固定为官方 iTdos。
|
|
94
|
+
|
|
95
|
+
1. 用 `microi_get_engine_code` 完整读取 `platform-saas-promotion` 和 `platform-saas-public-trial`,有分页时拼齐并核对完整 SHA-256。再通过 `microi_run_engine` 执行 `{Action:'Bootstrap'}`,读取 `Actor/Users/Settings/Roles`,确认当前会话有创建权限。按准确 Account 或 Id 解析活跃推荐人;姓名重名时先澄清,禁止猜测用户 Id。管理员可以为活跃用户创建,业务员默认只为自己创建。
|
|
96
|
+
2. 执行 `{Action:'Links'}`,先查该推荐人的活动。已有符合请求且启用、未过期的链接可复用,保留其他活动与业务数据。只有平台管理员的 `Actor.CanConfigure=true` 才能配置公开开通。配置缺失且用户已授权启用时,通过 `SaveSettings` 写入真实主租户前端 HTTPS 地址;不要把 API 域名、临时测试端口或别人的平台地址当成 WebBase。仅创建链接不隐含修改已经设定的开通策略。
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
// microi_run_engine:apiEngineKey='platform-saas-promotion'
|
|
100
|
+
// params 为下列对象;confirmExecution 使用同一 ApiEngineKey。
|
|
101
|
+
{ Action:'SaveSettings', Enabled:true, WebBase:'https://<主租户前端域名>',
|
|
102
|
+
TrialDays:14, DailyLimit:20, LinkLimit:50, ManagerRoleIds:[] }
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
上例为未配置时的默认值。已有试用天数、每日额度、单链接额度和管理角色应从 Bootstrap 回读并保留,除非用户明确要求调整;`ManagerRoleIds` 使用真实角色 Id 数组。保存后再次 Bootstrap 核对本分区配置。
|
|
106
|
+
3. 无合适活动时执行下列请求。`ReferralUserId` 必须来自第 1 步的权威用户目录;业务员额度和试用天数不能超过主租户设定值。
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
{ Action:'CreateLink', Title:'<推广活动名称>', ReferralUserId:'<sys_user.Id>',
|
|
110
|
+
TrialDays:14, MaxTenants:50, ValidDays:30, Remark:'<可选活动说明>' }
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
创建超时先按推荐人、活动名称和时间回读 Links,确认是否已创建;禁止盲目重试导致重复活动。取得 `Data.Id` 后执行 `{Action:'ShareLink', Id:'<活动Id>'}`,返回 `Data.Url` 才是可分享地址。不要手拼 `ref=<用户Id>` 或将活动 Id 代替 `LinkToken`;票据绑定推荐人、活动、运行分区、到期时间和版本。切换链接启停状态会撤销旧地址,之后需重新签发。
|
|
114
|
+
4. 回读 Links 核对归属、启用状态、期限、试用天数和额度。在全新、未登录的浏览器 context 打开 `Data.Url`,核对匿名 `platform-saas-public-trial` 的 Bootstrap 成功、表单与图形验证码可用。验收链接不需要实际创建客户租户;只有明确授权开库后才提交真实申请,并按同一 RequestId 回读任务、租户归属和登录地址,保留幂等及精确清理证据。
|
|
115
|
+
|
|
116
|
+
最终交付可点击的分享地址、推荐人、试用天数、链接到期时间及额度,并区分“链接已可访问”和“客户租户已实际开通”。若接口不存在或平台版本不足,走官方 SaaS 应用与内置微服务更新,不通过临时 SQL 绕过鉴权。
|
|
117
|
+
|
|
118
|
+
制作空数据库时,角色、账号绑定和权限快照必须作为同一初始模板处理。只保留明确声明的初始角色,按权威角色重建保留账号的 `RoleIds` 与等级;删除业务角色及孤立菜单权限,清空包含源业务菜单的角色权限快照。初始角色缺失、删除或等级不符时停止制作,不得根据账号现有角色列表、角色名称或高等级推测哪些角色应保留。
|
|
119
|
+
|
|
120
|
+
组织数据属于同一空库模板边界:只保留明确声明的初始组织和部门,将保留账号的部门绑定与名称同步归一,并清理旧版账号关系表。保护这些平台表的物理结构,初始组织缺失或已删除时停止制作;验收必须在新租户查看真实组织树,不能只检查角色数量。清理只能作用于制作过程的隔离副本。
|
|
121
|
+
|
|
122
|
+
安装历史只有能对应保留平台应用的稳定身份才可继承:非空 `StoreId` 优先,旧记录没有该字段时再核对非空应用身份;不能凭名称或前缀保留孤立记录。SQL 预览、临时副本执行、公开空库文件更新与新租户登录验收是不同证据层;源主库和既有测试租户都不能作为清理执行目标。
|
|
123
|
+
|
|
124
|
+
主库 `sys_osclients` 保存租户数据库/Redis/存储路由及影响整个 API 进程的平台级配置;目标租户建立上下文后,`sys_config` 和 `mci_system_setting` 从该租户自己的数据库读取。平台级配置必须遵守“主租户为准、子租户只能降额隔离”的规则:
|
|
125
|
+
|
|
126
|
+
- 所有可变业务逻辑默认必须由接口引擎编排,包括但不限于租户开通、开库、初始化、归属修复、官网个人中心、付费额度等 SaaS 业务流程。C# 后端只暴露原子 V8 能力,例如建库、导入空库模板、复制 `sys_config`、刷新 SaaS 缓存、补偿回滚、字段兜底等;不要把可变业务分支写死到 Controller 或 `TenantProvisioningService` 这类后端定制代码里。接口引擎缺少能力时,优先扩展 `V8.Method`/V8 引擎原子函数,再由接口引擎调用。
|
|
127
|
+
- 官方租户开通固定由 SaaS 包的 `platform-create-tenant` 编排:`platform-runtime-custom-hook` 的 Before 阶段可以阻断,`AuthorizeCurrentUserTenantProvisioning` / `ProvisionCurrentUserTenant` 只从可信主租户 DiyToken 派生所有者与密码材料;创建完成后的 Hook/审计失败只能返回 Warning,不能诱导重复创建。系统账号偏好/资料与租户系统设置分别由 `app.microi.sys_user`、`app.microi.sys-config` 单一拥有,SaaS/Store 不得复制这些 Managed ApiEngineKey。
|
|
128
|
+
- 租户开库失败时,先核对编排 `OsClientDbConn` 的真实账号与权限。业务库账号通常不能开库、创建用户或授权;应使用已有正确授权的管理账号更新编排,不通过 SQL/MCP 手工修复业务数据库。管理员页面必须同时显示中文原因、失败阶段、可执行的处理方法,以及可展开且已脱敏的原始异常链;区分密码/来源认证失败与数据库权限不足,不能只显示笼统失败或隐藏驱动原始错误。
|
|
129
|
+
- 旧版 UniApp 的 `microi-init` 是 SaaS 包继续托管的 Managed 兼容门面。匿名阶段只组合 `platform-os-client-by-domain` 与 `platform-sys-config` 的公开投影;原始 DiyToken 必须由 `GetCurrentToken` 和 `RefreshLoginUser(..., rawToken)` 在后端重新验证且绑定当前租户,菜单再由只允许该固定 Key 调用的 `GetLegacyInitMenuTree(rawToken, osClient?)` 复用 `SysMenuLogic` 权威角色过滤。禁止在匿名 V8 中直接通过 FormEngine 读取 `sys_menu`;域名解析到其它租户时返回目标 `OsClient` 并要求重试,禁止匿名跨租户读取配置或菜单。
|
|
130
|
+
- 主租户由运行环境决定:优先读取环境变量 `OsClient`,其次读取 `appsettings.json` 的 `AppSettings:OsClient`。只有这条主租户 `sys_osclients` 数据中的平台级字段会作为全局配置生效。
|
|
131
|
+
- 同一个主租户可以同时运行在 `Product/Internal`、`Product/Internet` 等多个分区;租户目录、后台任务领取、通知和批量平台应用维护都必须按当前节点的 `OsClientType + OsClientNetwork` 隔离。一次全量维护只证明当前分区,事故恢复必须先盘点所有活跃分区,再从各分区对应节点分别执行并等待 `SucceededCount=ExpectedCount、FailedCount=0`,随后各自以新幂等键做零安装/零更新复跑。禁止临时改租户网络字段、跨分区借用任务或并发维护可能指向同一物理库的重复租户记录。
|
|
132
|
+
- 大范围启动事故只允许受信后台编排器使用 `MaintenanceScope=StartupDependencies`,精确闭包固定为 `app.microi.store + app.microi.saas-engine`,并可显式启用 `StartupDependencyBootstrapOnly=true`。编排器必须先用权威当前分区目录校验 `TargetOsClients`,再在子任务仍为 `Pending` 时原子写入并强回读两应用范围与只自举标志;失败即取消,禁止退化为完整安装。工作器只从官方不可变包补齐 `platform-sys-menu` 和六项 SaaS 启动门面,七项物理契约强回读通过后终止,不写安装版本。该模式只恢复可登录性,不代表 API 进程的完整运行时已经就绪;新版后端接收流量前还必须从九个内置官方基础应用包补齐并回读全部接口引擎,后续完整应用更新仍走普通商城任务。未带标志的任务行为不得改变。
|
|
133
|
+
- API 启动配置只有十项白名单:`OsClient`、`OsClientType`、`OsClientNetwork`、`OsClientDbType`、`OsClientDbConn`、`OsClientRedisHost`、`OsClientRedisPort`、`OsClientRedisPwd`、`OsClientRedisDataBase`、`OsClientDbMongoConn`。除这十项外,部署/节点级运行参数与基础设施秘密从主控 `sys_osclients` 读取;允许子租户自行维护且需要浏览器判断的业务开关、入口显示和公开交互配置使用该租户 `sys_config` 实体字段,OAuth/第三方集成的凭据、RP/Origin/Issuer/Scope 与仅后端参数使用 `mci_system_setting`,未配置时使用代码安全默认值。官方 License 恢复次数/间隔与固定私钥挂载 `/app/microi_private.pem` 是信任链例外。禁止再增加 `MICROI_*`、`DOS_ORM_*`、自定义 `AppSettings` 节点或动态名称的环境变量读取。节点身份由平台自动生成。
|
|
134
|
+
- 存量畅捷通/微信 OAuth C# 协议网关有一组已发布到 SaaS 引擎的兼容字段:`OAuthReturnUrlOrigins`、`ChanjetOAuthState`、`ChanjetAesKey`、`ChanjetAppKey`、`WeChatTemplateAppId`、`WeChatTemplateAppSecret`、`WeChatTemplateId`、`WeChatMiniProgramAppId`。只能通过 Core 的租户绑定协议设置原子按请求权威 `OsClient` 读取,禁止使用主租户 `ConfigHelper` RuntimeConfigurationReader;整组字段不得复制给新租户,其中 OAuthState/AES Key/AppKey/AppSecret 不得进入 `V8.OsClientModel` 或前端投影且必须在审计中掩码。新集成不得继续扩展该兼容集合,仍使用当前租户 `mci_system_setting` + Managed ApiEngine。
|
|
135
|
+
- `ASPNETCORE_*`、`DOTNET_*` 仅用于 .NET 宿主;构建、安装、测试、MCP、发布脚本可使用自身进程变量,但 API 生产代码不得把它们当业务配置。新增 SaaS 运行字段必须配套独立或既有 Tab、幂等升级、缓存刷新、敏感字段脱敏、子租户不继承和源码扫描测试。
|
|
136
|
+
- 文件上传的租户业务开关与额度按“当前租户 `sys_osclients` → 代码默认值”解析;现行负向字段 `DisableFileUpload` 默认关闭/空值即允许上传,只有 `1/true` 才禁止。旧 `FileUploadEnabled` 只在新物理字段尚不存在的滚动升级节点回退读取,并须在新版 SaaS 表单隐藏。平台固定灾难保护、HTTP/Multipart/Form 和反向代理上限不可由租户覆盖,也不要求安装者维护额外上传环境变量。
|
|
137
|
+
- 类似 MQTT 端口、PressureGuard、V8Limits、OrmLimits、StartupLimits、SecurityGuard 这类影响整进程资源的配置,不能让每个子租户各自抬高全局上限。子租户同名隔离字段只能降低自己的并发、等待时间或资源额度,用于隔离弱租户、试用租户或异常租户。
|
|
138
|
+
- 修改 `sys_osclients` 的表、字段、数据源或配置值后,必须刷新 SaaS 引擎运行缓存,并回读验证字段 `Component`、`Data`、`Config`、实际数据值和前端真实消费结果。不要只看 MCP 写入成功。
|
|
139
|
+
- SaaS 配置只在启动、管理员保存 `sys_osclients` 或显式租户刷新时发布到共享 Redis。初始化数据库会话、创建 `V8.Dbs` 运行态对象、普通 FormEngine 请求和表单设计器保存不得冒充配置变更反复发布。
|
|
140
|
+
- JWT Key 由可信后端生成并持久化;SaaS 表单只读显示配置状态,不允许普通表单或 V8 写入 `AuthSecret`。手动接入旧库的 NULL/空白值必须支持原子写回,多节点竞争后回读持久胜者;重复刷新不能轮换有效 Key。只读状态查询不得初始化目标租户数据库。验收只记录是否已配置、是否稳定,不输出密钥原文。
|
|
141
|
+
- 扩展库缓存必须区分“尚未加载”和“已加载但为 0 条”;后者是有效结果。没有配置 `microi_database` 的租户不能在每次 V8 执行时重复查询、调用 `AddOrUptClient` 或打印“缓存 OsClient 配置到 Redis”。
|
|
142
|
+
- 多节点的缓存失效订阅只做本节点失效与数据库回源,禁止收到消息后再次发布形成回声。进程内初始化标记仅是可丢失优化,真正租户配置仍以共享数据库/Redis 为准。
|
|
143
|
+
- 新增平台级字段时,字段名建议保持英文稳定,例如 `PressureGlobalMaxConcurrentRequests`、`PressureV8MaxConcurrentExecutions`、`PressureOrmMaxConcurrentConnectionOpens`;字段标签和说明必须中文,说明中写清楚“主租户有效/子租户仅可降低”。
|
|
144
|
+
- 新租户记录不得复制主租户的数据库、鉴权、Redis/对象存储密钥或 MQ/MQTT/Search 凭据。共享基础设施地址与管理密钥只在服务端运行时解析,不持久化到子租户记录,也不进入 V8 投影。
|
|
145
|
+
- RabbitMQ 子租户必须使用独立 user/vhost/ACL,MQTT 必须使用独立账号密码,Search 必须使用限制到 `{osClient}_*` 的 API Key/用户。外部资源尚未真实创建时保持空凭据并失败关闭,禁止把主租户管理员凭据复制过去冒充完成。
|
|
146
|
+
- `V8.Cache`、`V8.HDFS`、RabbitMQ、MQTT、Search 分别强制 `Microi:{OsClient}:*`、`/{osClient}/...`、`microi.{osClient}.*`、`tenant/{osClient}/...`、`{osClient}_*` 命名空间。body/query 中的 `OsClient` 不能覆盖登录 Token 或 V8 上下文。
|
|
147
|
+
|
|
148
|
+
## 接口调用区分租户的三种方式
|
|
149
|
+
|
|
150
|
+
### 方式 1:Token 自动识别(最常用)
|
|
151
|
+
|
|
152
|
+
请求头携带 `Token`,平台自动识别用户所属租户。
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
GET /apiengine/get-products
|
|
156
|
+
Token: xxx-token-xxx
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 方式 2:URL 参数
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
GET /apiengine/get-products?OsClient=tenant_demo
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### 方式 3:特殊 URL 格式(无 Token、无参数)
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
GET /apiengine/get-products--OsClient--tenant_demo--
|
|
169
|
+
GET /apiengine/get-products--OsClient--tenant_demo--OsClientType--App--
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
> 适用于第三方回调(无法添加 Header)、支付/微信回调等场景。
|
|
173
|
+
|
|
174
|
+
## 跨租户操作(仅可信控制面)
|
|
175
|
+
|
|
176
|
+
普通 V8 的 `FormEngine`、`DataSourceEngine`、`TranslateEngine`、`WFEngine`、`Cache`、`HDFS`、MQ/MQTT、Search 和 `Dbs` 都必须绑定当前 Token/V8 上下文中的 `OsClient`。请求 body/query 里传入其它租户不能切换连接,也不能读取其它租户凭据。
|
|
177
|
+
|
|
178
|
+
租户开通、迁移、备份或平台管理员代维只能走明确的控制面服务/接口引擎:
|
|
179
|
+
|
|
180
|
+
- 调用者必须是 `Level >= 9999`,并再次校验目标租户白名单和操作类型;
|
|
181
|
+
- 使用专用原子能力,不通过通用 FormEngine 读取完整 `sys_osclients` 记录;
|
|
182
|
+
- 不把数据库、认证、Redis、存储、MQ/MQTT、搜索等连接与密钥投影进 V8;
|
|
183
|
+
- 每次操作写安全审计、幂等键和补偿状态,并对目标租户回读验收;
|
|
184
|
+
- 多节点部署使用共享租约和业务幂等,不能依赖进程静态锁。
|
|
185
|
+
|
|
186
|
+
### SaaS 数据库 ZIP 开库的进度与租约
|
|
187
|
+
|
|
188
|
+
通过 SaaS 引擎上传数据库 ZIP 创建租户时,必须把上传和还原建模为两个独立阶段:
|
|
189
|
+
|
|
190
|
+
- 上传使用分片会话并显示真实字节进度;暂停或网络中断后复用同一文件指纹续传,不能把上传百分比冒充数据库导入进度。
|
|
191
|
+
- 上传完成后提交平台持久后台任务。租户开通进度总数使用后端共享契约的固定 13 步,接口引擎、可信宿主原子和前端不得各自维护不同分母。
|
|
192
|
+
- 第 2 步是数据库 ZIP 校验与还原。该阶段应按真实 SQL 读取量推进总百分比,并显示已读取/总字节、SQL 百分比、已执行语句数、当前批次与语句类型、平均吞吐和动态预计剩余时间;不能长时间只显示静态的 `2 / 13`。
|
|
193
|
+
- 进度状态仅在距上次更新约 2 秒或新增约 16MB 数据时刷新;执行日志只记录阶段里程碑和 SQL 每跨过约 5% 的进度,前端只渲染最近 200 条。禁止按 SQL 行或每条语句推送日志,避免几十万条数据把共享任务表、SignalR 或浏览器 DOM 拖垮。
|
|
194
|
+
- 页面同时显示服务端心跳。单个百分比短时不变不等于卡死,应综合心跳、字节、语句数、批次和消息判断;失败、取消或中断必须保留最后真实进度和错误原因,只有成功终态才算开库完成。
|
|
195
|
+
|
|
196
|
+
租户开库使用平台可信后台上下文中的可续租共享锁:`Timeout` 是单次 Redis 租期,当前开库最长保护边界为 12 小时。普通 HTTP/V8 请求传入 `_BackgroundTaskId`、`_TrustedServerInvocation` 或伪造用户对象不能开启续租。持有者令牌不匹配、锁过期、Redis 所有权/续租确认失败或达到最长租约都必须失败关闭并停止推进;不能为了避免报错而把真实锁丢失降级成成功或 Warning。
|
|
197
|
+
|
|
198
|
+
自动续租只解决“正常长任务不因短 TTL 自然过期”,不能代替业务幂等、检查点、补偿状态和 fencing token。大库导入完成但域名绑定未完成时,应保留已经成功创建的租户和数据库,进入明确的域名补偿状态;不能因数据面域名失败重新导入整个数据库。接口引擎的通用锁配置读取 `../v8-api-config/SKILL.md`,长任务按钮和检查点读取 `../v8-menu-buttons/references/progressive-02-8-模式-f-后台任务按钮-长任务.md`。
|
|
199
|
+
|
|
200
|
+
## 缓存按租户隔离
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
// 推荐传逻辑 Key;服务端自动添加当前租户前缀
|
|
204
|
+
var key = 'Product:' + V8.Param.id;
|
|
205
|
+
V8.Cache.Set(key, value, 600);
|
|
206
|
+
|
|
207
|
+
// 完整当前租户 Key 继续兼容
|
|
208
|
+
var fullKey = 'Microi:' + V8.OsClient + ':Product:' + V8.Param.id;
|
|
209
|
+
|
|
210
|
+
// 其它租户的 Microi: 前缀会被服务端拒绝
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## 接口引擎中针对不同租户走不同逻辑
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
// 租户差异应来自当前租户的非敏感业务配置,不要硬编码某个“主租户”字符串
|
|
217
|
+
if (V8.OsClientModel.OrderApprovalMode === 'Direct') {
|
|
218
|
+
V8.FormEngine.UptFormData('Order', { Id: id, Status: 'Approved' });
|
|
219
|
+
} else {
|
|
220
|
+
await V8.WFEngine.StartWork({ FlowDesignId: 'order-flow', TableRowId: id });
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// App 端 vs PC 端不同返回
|
|
224
|
+
if (V8.OsClientType === 'App') {
|
|
225
|
+
return { Code: 1, Data: simplifiedList };
|
|
226
|
+
}
|
|
227
|
+
return { Code: 1, Data: fullList };
|
|
228
|
+
|
|
229
|
+
// 内网外网走不同 ERP 网关
|
|
230
|
+
var erpUrl = (V8.OsClientNetwork === 'Intranet')
|
|
231
|
+
? 'http://192.168.1.10/erp/api'
|
|
232
|
+
: 'https://erp.public.com/api';
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## 第三方密钥放租户动态设置(不要硬编码)
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
// ❌ 危险:密钥写在代码里,所有租户共用,无法独立轮换
|
|
239
|
+
var ak = 'AKIDxxxxxxxx';
|
|
240
|
+
|
|
241
|
+
// ✅ 浏览器需要判断的开关:使用 sys_config 实体字段
|
|
242
|
+
var giteeEnabled = V8.SysConfig.GiteeLoginEnabled === 1;
|
|
243
|
+
|
|
244
|
+
// ✅ 后端 V8 可读取当前租户 Secret 并直接调用供应商
|
|
245
|
+
var privateSettings = V8.SysConfig.ServerPrivateSettings || {};
|
|
246
|
+
var secret = privateSettings['Login.Gitee.ClientSecret'];
|
|
247
|
+
// 禁止 return secret、console.log(secret) 或写入前端可读字段。
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
> `mci_system_setting` 位于每个租户自己的数据库,只保存不能公开或仅供后端执行的配置;普通值与 Secret 都不会下发浏览器。Secret 保存认证密文,只在后端 V8 的当前租户 `ServerPrivateSettings` 中解密使用。能力开关和入口显示必须建成 `sys_config` 实体字段,禁止通过 `IsPublic` 或其它运行时勾选把私密记录公开。前端 V8、普通 FormEngine HTTP、匿名/访问密钥会话不能读取私密设置,后端 V8 也不能获得通用解密器。`sys_osclients` 自定义业务字段只保留存量兼容;共享基础设施字段由服务端强制移除,不能用自定义同义字段绕过安全代理。
|
|
251
|
+
|
|
252
|
+
## 用户扩展字段访问(同理)
|
|
253
|
+
|
|
254
|
+
平台 `sys_user` 也由表单引擎驱动。如给 `sys_user` 添加 `Wife` 字段:
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
// V8 代码中可访问
|
|
258
|
+
V8.CurrentUser.Wife;
|
|
259
|
+
|
|
260
|
+
// SQL 数据源中可访问
|
|
261
|
+
SELECT * FROM Contact WHERE OwnerId = $CurrentUser.Id$ AND Spouse = $CurrentUser.Wife$
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## 常见错误
|
|
265
|
+
|
|
266
|
+
- 旧库升级的内置应用包包含定时任务时,升级内核按“资源独立提交 → 幂等保存并回读 Quartz/任务元数据 → 确认安装版本”执行。仅程序集白名单包及不可伪造的宿主授权可进入该兼容流程;普通应用安装仍必须使用持久后台任务分片。任一阶段失败不推进 ServerVersion,修复后从原升级入口重试,不手动抬高版本或伪造任务信封。
|
|
267
|
+
|
|
268
|
+
❌ 绕开 `V8.Cache` 使用底层 Redis → 租户数据串号(V8 已不再暴露底层句柄)
|
|
269
|
+
❌ MongoDB DbName 不带 OsClient → 数据混淆
|
|
270
|
+
❌ 把 OsClientModel 字段直接返回给前端 → 密钥泄漏
|
|
271
|
+
❌ 查询 `mci_system_setting.SecretCipher` 或给 V8 暴露通用解密器 → 密钥边界失效
|
|
272
|
+
❌ 在前端硬编码 OsClient → 一改全改,应通过 token/URL 自动识别
|
|
273
|
+
❌ 跨租户操作不验证当前用户权限 → 越权风险
|
|
274
|
+
❌ 子租户缺少 MQ/MQTT/Search 独立凭据时回退主账号 → 全平台越权
|
|
275
|
+
|
|
276
|
+
## 检查清单
|
|
277
|
+
|
|
278
|
+
- 子租户授权使用官方 SaaS 应用的 `sys_osclients.LicenseProductType` 与 `LicenseExpirationDate`(UTC)字段;两项留空继承主授权。只允许主租户超级管理员设置,不能超过已验签主授权的版本和日期;运行时再次裁剪。两项不得通过主配置合并自动复制到子租户。不要在可编辑 V8 里代替可信授权边界。
|
|
279
|
+
- 授权到期文案和提前天数在消息通知页设置。官方与主租户策略分别触发,不能因官方已触发或未触发而跳过主租户检查。签发帐号 `sys_user.LicenseExpirationDate` 未设置表示永久有效,但可签发版本及请求日期仍需校验。
|
|
280
|
+
|
|
281
|
+
- [ ] 缓存只通过 `V8.Cache` 使用逻辑 Key 或当前租户完整 Key
|
|
282
|
+
- [ ] 所有 MongoDB DbName 都包含 `V8.OsClient`
|
|
283
|
+
- [ ] 当前租户自有的业务集成密钥可放 `V8.OsClientModel`,共享 Redis/存储/MQ/MQTT/Search 凭据只能由服务端托管
|
|
284
|
+
- [ ] 跨租户操作前校验权限
|
|
285
|
+
- [ ] 不向前端返回 `V8.OsClientModel`
|
|
286
|
+
- [ ] 子租户数据库账号只授权本租户库,MQ/MQTT/Search 独立凭据已真实创建
|
|
287
|
+
- [ ] 文件、队列、Topic、索引均由服务端规范为当前租户命名空间
|
|
288
|
+
- [ ] 无扩展库租户重复执行 V8 时不会重复刷新 SaaS 配置;真实 `sys_osclients` 保存后各节点能按租户失效并回源
|
|
289
|
+
- [ ] ZIP 开库区分上传与还原进度,使用固定 13 步、低频明细、服务端心跳和有界日志
|
|
290
|
+
- [ ] 开库锁只由可信持久后台任务自动续租;真实租约丢失失败关闭,所有副作用仍具备幂等、检查点和 fencing token
|
|
291
|
+
|
|
292
|
+
## Microi.AI 中转站租户凭据
|
|
293
|
+
|
|
294
|
+
- `mic_ai` 的 `Microi.AI中转站.ApiKey` 是租户调用吾码官方中转站的用户凭据。运行时不得因为该字段为空而静默创建、回退到当前用户字段或绕过校验,否则管理员无法判断真实配置来源。
|
|
295
|
+
- 老租户由用户在吾码官网个人中心复制 ApiKey 后填写到本租户的 `mic_ai` 中转站记录;空值应返回明确配置错误。
|
|
296
|
+
- 官网创建新 SaaS 租户时,必须先取得当前官网账号的 ApiKey,再由租户初始化服务写入新库 `mic_ai` 的 `Microi.AI中转站` 记录。该自动写入只发生在受控开库流程,不得散落到普通 AI 对话请求中。
|
|
297
|
+
- 开库入口把 ApiKey 传给后台 worker 后,worker 还必须继续显式传入最终的原子初始化方法;不能只在父接口或中间参数中“带过”。每个异步/后台边界都应对空值立即失败,避免租户创建成功但 `mic_ai.ApiKey` 静默为空。
|
|
298
|
+
- 自动化验收必须通过新租户 `admin` 登录回读 `mic_ai`,只输出“非空、长度、与官网账号 ApiKey 是否一致”等布尔结果,不得把真实 ApiKey 写入日志、截图或测试报告。
|
|
299
|
+
- 中转模型公开目录只返回模型 Id、显示名、厂商等非敏感字段,可匿名读取;严禁把官方上游模型的 ApiKey、Endpoint 私密配置随模型列表返回前端。
|
|
300
|
+
|
|
301
|
+
### 旧结构空库制作验收
|
|
302
|
+
|
|
303
|
+
空库脱敏生成器应只读实际物理列;组织机构旧表缺少可选父级名称列时,只写已有父级 Id,不为制作模板修改主库结构。物理字段发现失败应在输出清理 SQL 前失败关闭。验收同时覆盖有该列、缺少该列及读取失败,最终检查隔离副本和官方空库下载包。
|
|
304
|
+
|
|
305
|
+
应用文件与版本清理不得在 MySQL 5.7 的 DELETE 外连接中用 `Id = AppId OR AppKey = AppId`。先在隔离副本内物化带主键的 Id/AppKey 保留集合,分别覆盖当前商城 Id、历史 AppKey、业务应用、孤立记录与 NULL;验证新旧结果一致,源主库只读。真实 SQL 耗时与 Node 生成器测试需分别记录。
|