@microi.net/cli 5.1.7 → 5.1.9

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
2
  name: ai-engine
3
- description: Microi AI 引擎、模型代理、NL2SQL/NL2V8 与知识库规范。用于模型路由、密钥和订阅配额、Schema/Skill 关键词检索与可选向量融合、提示词安全、流式响应、租户隔离和验收。
3
+ description: Microi AI 引擎、MiniMax 图片/音乐/视频生成与预览、模型代理、NL2SQL/NL2V8 和知识库规范。用于媒体生成、模型路由、密钥与订阅配额、Schema/Skill 检索、流式响应、租户隔离和验收。
4
4
  ---
5
5
 
6
6
  > **Codex 非阻塞自动更新:** 当前宿主为 Codex 时,吾码 CLI、Codex 插件与工作区 AI/MCP 由后台自动更新;需要诊断时读取 `../microi-codex-installer/SKILL.md`。更新失败、等待空闲或尚未重载均不得阻断当前、正在进行或新建任务。非 Codex 宿主跳过此项。
7
7
 
8
8
  # Microi AI Engine
9
9
 
10
- 平台视频生成的受控 HTTP 入口为 `/api/Ai/CreateMiniMaxVideo`、`/api/Ai/GetMiniMaxVideoTask`、`/api/Ai/GetMiniMaxVideoFile`、`/api/Ai/PersistMiniMaxVideoFile`;AI 工作流入口统一位于 `/api/AIWorkFlow/*`。调用方只提交业务参数和模型选择,供应商密钥、租户配额、任务归属和文件读取权限由服务端判定。`PersistMiniMaxVideoFile` 只能将当前登录用户所属、且已成功完成的 MiniMax 视频任务文件持久化到当前租户 HDFS;禁止把该入口作为任意 URL 搬运器,任务归属、文件来源和租户边界必须由服务端重新校验。
10
+ 平台媒体生成的受控 HTTP 入口包括 `/api/Ai/GenerateMiniMaxImage`、`/api/Ai/GenerateMiniMaxMusic`、`/api/Ai/CreateMiniMaxVideo`、`/api/Ai/GetMiniMaxVideoTask`、`/api/Ai/GetMiniMaxVideoFile`、`/api/Ai/PersistMiniMaxVideoFile`;AI 工作流入口统一位于 `/api/AIWorkFlow/*`。调用方只提交业务参数和模型选择,供应商密钥、租户配额、任务归属和文件读取权限由服务端判定。生成结果必须先进入当前租户 HDFS 或受控临时句柄,浏览器不接触供应商密钥、图片 Base64、音频十六进制或原始视频任务 Id。`PersistMiniMaxVideoFile` 只能转存当前登录用户所属且已完成的任务,禁止作为任意 URL 搬运器。
11
11
 
12
12
  ## 能力
13
13
 
@@ -53,12 +53,17 @@ AI 业务统一实现在 `Microi.Server/Microi.AI`。`Microi.Server/Microi.net.A
53
53
 
54
54
  - 模型 Provider、Endpoint、ApiKey、AuthPrefix 和上游模型 Id 只保存在服务端受保护配置。
55
55
  - 普通用户使用平台签发的受限 API Key/订阅身份,不能枚举或读取上游密钥。
56
+ - MiniMax 对话媒体必须区分意图模型与生成模型:`MiniMax-M3` 只负责识别普通对话、绘图或音乐意图;图片固定走 `GenerateMiniMaxImage + image-01`,纯音乐固定走 `GenerateMiniMaxMusic + music-2.6`。不得让文本模型用说明文字冒充媒体生成,也不得声称图片/音乐是 `MiniMax-M3` 原生输出。
57
+ - 图片请求限制为 1~4 张和受控比例,音乐当前仅向平台管理员开放且固定无人声、44.1kHz、256kbps、MP3。两者都使用稳定 `RequestId` 和共享幂等;相同参数回放、参数冲突拒绝,上游结果不确定时禁止换 Id 盲重试。成功内容由服务端校验后直接写入当前租户公有 HDFS。
58
+ - 聊天附件的公有媒体 URL 优先按当前运行租户 `FileServer + FilePath` 解析,禁止写死域名或沿用其它租户的前缀。图片使用 Element Plus `el-image` 的 `preview-src-list` 原页放大,不能套 `target="_blank"`;音乐使用 `<audio controls preload="metadata">` 在线播放。媒体是结构化附件,文本才走安全 Markdown 渲染,禁止拼接任意 HTML 绕过 URL/类型校验。
59
+ - Provider/中转账号未开通音乐产品、额度不足或上游停用时必须返回可诊断失败,不生成占位音频、不伪报成功。图片、音乐和视频的真实可用性都需用目标租户登录态调用及媒体 GET/播放回读证明,源码存在或接口 HTTP 200 不能替代生成成功。
56
60
  - MiniMax 视频生成属于可复用供应商原子能力,应实现在 `Microi.AI`,Controller 只读取可信用户/`OsClient`、绑定参数并传递取消信号。理由是上游密钥隔离、异步 `task_id → file_id → download_url` 协议、订阅额度和跨节点幂等都不是某个可编辑接口引擎应复制的业务逻辑;具体文章、提示词和分发编排仍可留在 Job/接口引擎/发布 Skill。
57
61
  - MiniMax Token Plan Key 与按量 API Key 是相互独立的凭据,必须复用现有服务器端 Provider/ApiKey 受保护配置,不新增 API `AppSettings`、`MICROI_*` 环境变量或浏览器可见 Key。视频创建、查询和下载仅允许官方 HTTPS Host `api.minimaxi.com`。
58
62
  - 视频创建必须要求调用方稳定 `RequestId`,先在当前租户共享 Redis 以 `OsClient + 用户 + RequestId` 原子 `NX` 占位;Redis 不可用时失败关闭。相同 RequestId/参数回放返回原任务,不同参数冲突拒绝;上游 POST 超时或结果不确定时禁止自动换 RequestId 重试。查询不再次扣生成额度。
59
63
  - 原始 MiniMax `task_id`/`file_id` 不下发。服务端返回由供应商 Key 签名、绑定当前用户和用途的短句柄;查询/下载验签后才还原。Key 轮换会使旧句柄失效,应先完成或重新登记在途任务。
60
64
  - 当前官方模型边界必须实时校准:`MiniMax-Hailuo-2.3` 支持文生/图生,`MiniMax-Hailuo-2.3-Fast` 仅图生且必须有首帧,首尾帧使用 `MiniMax-Hailuo-02`。Hailuo 2.3 的画质优先上限与平台默认值是 6 秒 / 1080P,时长优先上限是 10 秒 / 768P,两者不能同时最大;API 不提供 fps 参数,必须用媒体探针记录真实帧率,禁止把插帧/画布规格冒充模型原生能力。当前 Token Plan 使用统一用量条、5 小时固定窗口和周窗口,控制台是剩余额度事实源,不再把固定“每天 N 条”写成官方配额。需要自动生成时,在 `Microi.AI` 增加只读、脱敏、管理员限定的 `https://www.minimaxi.com/v1/token_plan/remains` 安全原子能力;不得由浏览器或可编辑 V8 读取 Provider Key,也不得把客户端今日计数当成供应商权威额度。
61
65
  - MiniMax 视频任务返回静音画面。需要人物对白时,男/女语音必须通过 `Microi.AI` 的 `GenerateMiniMaxSpeech` 受保护原子能力生成:固定 `speech-2.8-hd`、固定男女系统音色、稳定 RequestId、共享 Redis 幂等,并直接转存租户 HDFS;再由可靠 Worker 按时间轴混音、加准确字幕。无法证明口型同步时使用画外音或反打镜头。背景音乐使用 `GenerateMiniMaxMusic` 并在人声下压低。运行节点尚未部署 Speech 能力、额度未核实或母版混音/探针证据缺失时失败关闭,禁止静音、仅配乐、浏览器直连供应商或伪称模型原生带声。
66
+ - 管理端【AI视频】应按 `TaskHandle` 轮询任务,成功后优先转存 HDFS,并用 `<video controls preload="metadata">` 原页预览和明确下载按钮消费同一个已校验地址。临时 URL、生成完成、HDFS 转存、媒体可播放和外部平台发布是五个不同事实,必须分别验收。
62
67
  - 使用 Microi.AI 中转站时,租户侧 AI Bootstrap 通过官方 `official_ai_relay_models` 发现可用运行模型。该接口是跨租户只读公共契约,必须保持启用、允许匿名 HTTP 调用,并且只返回模型标识、展示名等公开白名单字段,绝不能返回中转密钥或上游 Endpoint。消费者不得把 `NoAuth` 静默伪装为“没有配置模型”;应返回可诊断错误,同时前端显示明确空态。
63
68
  - PC、UniApp 和其它客户端通过 `POST /apiengine/{key}` 发送的 JSON Body 必须完整进入 `V8.Param`;兼容入口 `/api/ApiEngine/Run` 的 JSON Body 还必须包含 `ApiEngineKey`。API 层只负责请求绑定和清除客户端伪造的可信字段,模型选择、权限策略与对话逻辑仍全部位于 `Microi.AI` 或受控 AI 接口引擎中。
64
69
  - 当前计量记录除问题摘要外还可能持久化完整 `Question`、`Answer`,部分诊断日志也会输出问题或摘要。处理现有版本时必须把这些字段视为敏感业务数据,限制查询权限和留存;不要声称已经全面脱敏。
@@ -13,77 +13,77 @@ description: Microi 应用商城开发、打包、安装和升级规范。用于
13
13
 
14
14
  `AppType` 是历史复用字段:旧包/接口曾把它用于官方/社区来源,也曾把它作为运行类型回退。新代码不能把 `AppType` 当事实源;只在读取旧数据时回退,写入新数据使用 `ApplicationType + PublisherType`。
15
15
 
16
- 客户已有的全局 V8、表单配置、菜单、字段和自定义代码必须保留。升级采用存在性检查、差异合并和包隔离,禁止整表覆盖或把发布方租户数据原样复制到目标租户。
17
-
18
- ## 平台升级的应用商城边界(强制)
19
-
20
- - 表、字段、Tab、菜单、权限、接口引擎、事件、数据源、页面、打印、工作流、任务和可幂等种子数据都应通过应用包升级;不得为这些资源在 `Microi.Server/Microi.Upgrade/` 新增租户定制 .NET 代码。
21
- - 有官方 MCP 权限时,固定使用 `microi_itdos`(`https://api.itdos.com`、`OsClient=iTdos`)更新官方母版、制作并发布对应应用,按内容哈希/包版本回读后,再由目标租户 MCP 安装或更新。无官方权限时只通过当前用户自己的 MCP/Manifest 更新其数据库并回读,不得假借通用升级器越权发布官方应用。
22
- - `Microi.Upgrade` 只保留应用商城/安装器启动前必需的核心物理兼容或协议迁移,并要求持久化版本门、共享租约、幂等、失败不推进版本。禁止每次启动对每个租户重跑不断增长的历史迁移清单。
23
- - 平台通用缺陷的交付证据必须分开记录:源码修复、官方母版资源、商城包发布后回读、目标租户后台安装任务、目标租户资源回读和真实 UI/接口验收;其中任一步未完成都不能笼统称为“已发布并安装”。
16
+ 客户已有的全局 V8、表单配置、菜单、字段和自定义代码必须保留。升级采用存在性检查、差异合并和包隔离,禁止整表覆盖或把发布方租户数据原样复制到目标租户。
24
17
 
25
- ## 包内容
18
+ ## 平台升级的应用商城边界(强制)
19
+
20
+ - 表、字段、Tab、菜单、权限、接口引擎、事件、数据源、页面、打印、工作流、任务和可幂等种子数据都应通过应用包升级;不得为这些资源在 `Microi.Server/Microi.Upgrade/` 新增租户定制 .NET 代码。
21
+ - 有官方 MCP 权限时,固定使用 `microi_itdos`(`https://api.itdos.com`、`OsClient=iTdos`)更新官方母版、制作并发布对应应用,按内容哈希/包版本回读后,再由目标租户 MCP 安装或更新。无官方权限时只通过当前用户自己的 MCP/Manifest 更新其数据库并回读,不得假借通用升级器越权发布官方应用。
22
+ - `Microi.Upgrade` 只保留应用商城/安装器启动前必需的核心物理兼容或协议迁移,并要求持久化版本门、共享租约、幂等、失败不推进版本。禁止每次启动对每个租户重跑不断增长的历史迁移清单。
23
+ - 平台通用缺陷的交付证据必须分开记录:源码修复、官方母版资源、商城包发布后回读、目标租户后台安装任务、目标租户资源回读和真实 UI/接口验收;其中任一步未完成都不能笼统称为“已发布并安装”。
24
+
25
+ ## 包内容
26
26
 
27
27
  - Manifest:应用 Key、版本、兼容平台版本、依赖和资源清单。
28
28
  - 数据模型:表、字段、菜单、角色权限、接口引擎、事件、数据源、页面、打印、工作流、任务。
29
29
  - 源码与构建:私有源码包与可部署构建包分离,记录 SHA-256。
30
30
  - 安装/升级脚本:幂等、可恢复、可回读;不包含租户密钥、Token、连接串或 License keys。
31
- - 迁移采用“先扩展、后迁移、再收缩”,支持新旧节点短暂并存。
32
-
33
- ## 接口引擎资源所有权(强制)
34
-
35
- - 新发布包必须声明 `ResourcePolicies.ApiEngines`,不得再依赖“同 Key 直接覆盖”。官方不可随租户修改的核心使用 `{ Ownership:'Application', UpgradePolicy:'Managed' }`;提供给租户改业务的 Hook 使用 `{ Ownership:'Tenant', UpgradePolicy:'CreateIfMissing' }`。
36
- - 发布器从上一版 `AppPakcet.SysApiEngines` 计算 `BaseHash`;导入成功后把本版摘要写入 `sys_microistoreversion.InstallResult.ResourceState.ApiEngines`。更新判定固定为 Base/Local/Incoming:`Local == Base` 才允许更新;`Local != Base && Local != Incoming` 必须回滚并报告冲突,禁止静默覆盖。
37
- - `CreateIfMissing` 只在目标 Key 不存在时创建,存在时不得对齐 Id、源码、启用状态或其它字段。扩展模板发布后即归租户维护;后续版本禁止把同一 Key 改回 `Managed` 接管,确需新的官方核心时发布新 Key 并显式迁移。
38
- - 官方功能采用“Managed 核心 + CreateIfMissing Hook”。核心只提供稳定协议和默认行为;客户日志、写表、通知和业务动作放 Hook,并以稳定 `EventId`、唯一约束或 outbox 幂等。安全核心冲突不自动三方合并代码。
39
- - 历史包未声明策略时只能按旧兼容流程安装;重新发布时发布器必须生成策略。验收至少覆盖首次安装、未修改核心升级、核心被改后冲突回滚、Hook 被改后保持原样、重复安装和两节点竞态。
31
+ - 迁移采用“先扩展、后迁移、再收缩”,支持新旧节点短暂并存。
32
+
33
+ ## 接口引擎资源所有权(强制)
34
+
35
+ - 新发布包必须声明 `ResourcePolicies.ApiEngines`,不得再依赖“同 Key 直接覆盖”。官方不可随租户修改的核心使用 `{ Ownership:'Application', UpgradePolicy:'Managed' }`;提供给租户改业务的 Hook 使用 `{ Ownership:'Tenant', UpgradePolicy:'CreateIfMissing' }`。
36
+ - 发布器从上一版 `AppPakcet.SysApiEngines` 计算 `BaseHash`;导入成功后把本版摘要写入 `sys_microistoreversion.InstallResult.ResourceState.ApiEngines`。更新判定固定为 Base/Local/Incoming:`Local == Base` 才允许更新;`Local != Base && Local != Incoming` 必须回滚并报告冲突,禁止静默覆盖。
37
+ - `CreateIfMissing` 只在目标 Key 不存在时创建,存在时不得对齐 Id、源码、启用状态或其它字段。扩展模板发布后即归租户维护;后续版本禁止把同一 Key 改回 `Managed` 接管,确需新的官方核心时发布新 Key 并显式迁移。
38
+ - 官方功能采用“Managed 核心 + CreateIfMissing Hook”。核心只提供稳定协议和默认行为;客户日志、写表、通知和业务动作放 Hook,并以稳定 `EventId`、唯一约束或 outbox 幂等。安全核心冲突不自动三方合并代码。
39
+ - 历史包未声明策略时只能按旧兼容流程安装;重新发布时发布器必须生成策略。验收至少覆盖首次安装、未修改核心升级、核心被改后冲突回滚、Hook 被改后保持原样、重复安装和两节点竞态。
40
40
 
41
41
  ## 安装流程
42
42
 
43
43
  1. 校验签名/哈希、包版本、平台兼容性、依赖和磁盘/配额。
44
44
  2. 创建全局唯一 `InstallationId` 和稳定幂等键。
45
- 3. 使用后台任务执行,阶段性持久化进度与 checkpoint。
46
- 4. 按 Manifest 差异创建缺失资源;已有资源只更新包拥有且允许升级的属性。
47
- 5. `PostSchema` 完成后,在独立 `ScheduleJobs` checkpoint 中幂等安装定时任务并回读 Quartz 运行元数据。
48
- 6. 写入成功后刷新共享缓存版本。
49
- 7. 回读表、字段、引擎、菜单、权限、页面、定时任务等关键资源。
50
- 8. 做 HTTP、UI 和权限冒烟;全部成功后才标记安装版本。
45
+ 3. 使用后台任务执行,阶段性持久化进度与 checkpoint。
46
+ 4. 按 Manifest 差异创建缺失资源;已有资源只更新包拥有且允许升级的属性。
47
+ 5. `PostSchema` 完成后,在独立 `ScheduleJobs` checkpoint 中幂等安装定时任务并回读 Quartz 运行元数据。
48
+ 6. 写入成功后刷新共享缓存版本。
49
+ 7. 回读表、字段、引擎、菜单、权限、页面、定时任务等关键资源。
50
+ 8. 做 HTTP、UI 和权限冒烟;全部成功后才标记安装版本。
51
51
 
52
52
  安装中断后从 checkpoint 幂等恢复;不能依赖当前 API 节点内存。
53
53
 
54
- ## 权限与租户
54
+ ## 权限与租户
55
55
 
56
56
  - 商城定义、安装、升级、卸载和应用源码只允许 `Level >= 9999`。
57
- - “吾码官方平台”不能只按 `OsClient`、域名或前端变量判断:服务端必须同时校验官方 `OsClient`,并确认当前节点固定只读挂载 `/app/microi_private.pem` 的公钥部分与内嵌官方 License 信任根匹配;本地源码开发可从私有子仓库兼容查找。任意自建私钥不能建立官方身份。官方平台前端隐藏安装、更新、重新安装、离线安装和批量安装入口,后端仍必须拒绝这些写操作。
58
- - 官方平台是应用发布源,连安装器的 `ValidateOnly` 也必须拒绝,避免通过“只验证”绕过发布源隔离。发布源只做包正文、版本和资产 Hash 回读;真实安装、更新及预检必须切换到非官方目标租户或本地非发布源环境。
57
+ - “吾码官方平台”不能只按 `OsClient`、域名或前端变量判断:服务端必须同时校验官方 `OsClient`,并确认当前节点固定只读挂载 `/app/microi_private.pem` 的公钥部分与内嵌官方 License 信任根匹配;本地源码开发可从私有子仓库兼容查找。任意自建私钥不能建立官方身份。官方平台前端隐藏安装、更新、重新安装、离线安装和批量安装入口,后端仍必须拒绝这些写操作。
58
+ - 官方平台是应用发布源,连安装器的 `ValidateOnly` 也必须拒绝,避免通过“只验证”绕过发布源隔离。发布源只做包正文、版本和资产 Hash 回读;真实安装、更新及预检必须切换到非官方目标租户或本地非发布源环境。
59
59
  - 所有资源按目标 `OsClient` 写入;包内不能携带源租户 `OsClient`、数据库、Redis、对象存储、MQ/MQTT、AI 或第三方密钥。
60
60
  - 按钮调用后台安装接口时,前端只传应用/版本/安装 Id;目标租户和管理员身份由 Token 确定。
61
61
  - 每次安装、更新、重新安装生成稳定 `OperationId`。官方计数服务用共享数据库事件表唯一约束去重,并在同一事务内登记事件和递增 `InstallCount`;重试、跨节点和响应丢失不得重复计数。
62
- - “全部安装/更新”固定只处理 `ApplicationType=Platform` 的官方平台应用中未安装与存在新版本的项目,不得把 UniApp、Web、MicroService 或其它社区/AI 应用整库安装;已是最新版的应用不重新安装。批量计划、子项状态、checkpoint 和进度必须持久化到共享数据库/后台任务,支持多节点抢占、失败重试和重启恢复,不能依赖进程内集合或浏览器状态。
63
- - 必须随所有后端版本自动落地的平台基础能力,仍要封装成受信任的官方 Platform 应用包,再由升级器调用统一 `import-microi-store-package` 幂等导入;禁止把表、字段、页面或微服务复制成定制 C# 迁移。身份验证、登录方式、个人中心与租户系统设置使用 `app.microi.saas-engine.json`:携带 `mci_system_setting`、`mci_user_external_identity`、默认设置和平台内置微服务。默认行必须使用 `InsertIfMissing + ConfigKey`,只补缺失,不覆盖 `ValueSource=Tenant` 的租户值或租户后来明确关闭的功能。小型平台启动微服务应以 `Source=NotIncluded + Build=DatabaseOnly + StorageMode=db` 随程序集交付并接受 256 文件/5MB、逐文件哈希和无源码门禁,使新租户在 HDFS 故障时仍能打开商城与恢复入口;普通应用安装、源码编辑和文件能力继续失败关闭,不得伪装成全平台健康。
64
- - 批量任务已经以“一个应用”为外层持久化恢复单元。规模可控的小型官方包应在一个事务中完成,避免对同一包体按 8 个字段反复下载、解析和重新排队;超过字段、表、DDL、流程、随包数据或资产安全阈值的大包继续使用内部 checkpoint 分片。热更新发现旧版批量计划不含 `ApplicationType` 时,必须丢弃旧计划并重新盘点,不能继续安装历史计划中的社区应用。
65
- - MySQL 宽表触发 65,535 字节行内上限时,只允许把不参与索引的 `varchar` 配置列无损提升为 `mediumtext`,并把类型覆盖持久化到后台任务 checkpoint;索引列和非行宽错误必须失败关闭。发布包对长连接串、密钥、回调地址、域名/白名单等字段应直接使用 `mediumtext`,同时更新 `DiyFields` 与建表 DDL,不能长期依赖安装时猜测。
66
- - 卸载是破坏性操作,必须明确列出将删除/保留的资源、二次确认并优先软删除/归档业务数据。
67
-
68
- ## 联邦商城源、公开范围与历史版本(强制)
69
-
70
- - 每个主租户和子租户都可以发布自己的应用;应用行用 `IsPublic` 表达公开范围,缺省/历史空值按公开兼容。公开应用允许未登录来源读取和安装,私有应用只允许来源登录成功后的授权身份读取,列表、详情、版本接口都必须重复执行这一权限判断。
71
- - 商城来源以 `ApiBase + OsClient` 唯一定位。添加来源先只读发现系统标题、验证码策略和公开应用数;需要私有应用时再登录。帐号、密码、Token 不能写浏览器配置或商城来源 JSON;密码只用于本次登录,长会话 Token 以 `MCP/Mobile` 非 PC 客户端签发,并由当前租户后端加密保存到 `mci_system_setting`,浏览器只持有不具备取密能力的凭据 Key。
72
- - 后端来源代理必须固定已保存的 `ApiBase + OsClient`,拒绝过期 Token、访问密钥会话、非超级管理员、非 HTTPS 外网地址、重定向漂移和超限响应;Token 不得返回浏览器、日志、审计或应用包。退出登录同步删除服务端密文。
73
- - 商城主页面统一承载应用市场、已安装、我发布的应用、安装离线包和来源管理,不能再通过独立菜单或路由割裂上下文。来源增删改启停逐项自动保存;来源管理、详情和复杂配置使用平台统一 `80%` 可拖动大圆角 Dialog,遮罩服从 `sys_config.DisableFormMaskBlur`。
74
- - 每张应用卡必须显示预览图、公开范围、分类、最新版本、当前租户已安装版本及状态色。来源卡必须显示其公开数和当前授权可访问总数;平台官方发布节点只显示“平台官方应用源”身份标记,不显示安装、更新或重新安装操作。
75
- - 安装可明确选择 `sys_microistore` 当前版本或 `mic_data_version` 中仍含完整包正文的历史快照;后台任务必须把 `StoreVersionId` 一直传到详情取包并把实际安装版本写回 `sys_microistoreversion`。回退旧版属于重新安装,不得静默换成最新版。
76
- - 应用详情的版本选择必须服务端分页和搜索,默认每页不超过 20 条;当前版本固定置顶,历史版本只返回仍包含完整包正文的可安装状态。禁止用 `_PageSize:500` 或一次加载全部版本后在浏览器过滤。翻页、搜索与页大小切换都必须保持已选版本语义并显示总数。
77
- - 商城详情、来源管理等 Teleport 弹层必须使用宿主级固定遮罩,毛玻璃覆盖完整可视区域;标题栏拖动按弹层真实尺寸限制四边,窗口缩放后重新限制,不能依赖固定像素最大位移或允许内容越出视口。
78
- - “我发布的应用”只读取当前登录用户拥有的记录,可以包含草稿和构建失败项;普通商城列表只读取已发布项。两者必须在服务端按 Owner 和发布状态过滤,不能依赖浏览器过滤后再分页。
79
-
80
- ## 发布版本与资源选择
81
-
82
- - 发布器必须把用户请求的精确版本传给资产准备器,并断言 `RequestedVersion == Prepared.PackageVersion == AppPakcet.PackageInfo.Version`;版本不存在就失败,禁止静默改用最新版本。
83
- - `SelectMenu`、`SelectTable`、`SelectApiEngine` 必须从当前发布包的显式选择持久化;不能读取商城行上一次保存的选择来决定本次包内容。
84
- - 发布完成后同时回读商城版本行、包正文和构建资产,逐项核对版本、数量与 SHA-256;任一处漂移即发布失败。
85
- - 官方内置前端应用只能有一个发布源码根。默认租户工作副本与受审计的独立 Git 源码仓库不能同时成为事实源;若使用独立仓库,必须提交一个发布契约并让构建、跨工程测试、所有程序集内置包共同读取它,正式发布还要证明源码根来自无未提交修改的 Git 提交。前端主包只提供通用宿主、诊断和恢复入口,不复制完整业务源码。HDFS/CDN 运行镜像必须回读到同一 `RuntimeManifestHash` 后才可启用,不能用较新的镜像静默覆盖较旧数据库包,也不能用较新的数据库包静默覆盖未验签镜像。
86
- - `ScheduleJobs` 是一等包资源,必须在 `PostSchema` 之后独立安装、持久化 checkpoint 并回读运行状态;任务失败时不得写入成功版本。
62
+ - “全部安装/更新”固定只处理 `ApplicationType=Platform` 的官方平台应用中未安装与存在新版本的项目,不得把 UniApp、Web、MicroService 或其它社区/AI 应用整库安装;已是最新版的应用不重新安装。批量计划、子项状态、checkpoint 和进度必须持久化到共享数据库/后台任务,支持多节点抢占、失败重试和重启恢复,不能依赖进程内集合或浏览器状态。
63
+ - 必须随所有后端版本自动落地的平台基础能力,仍要封装成受信任的官方 Platform 应用包,再由升级器调用统一 `import-microi-store-package` 幂等导入;禁止把表、字段、页面或微服务复制成定制 C# 迁移。身份验证、登录方式、个人中心与租户系统设置使用 `app.microi.saas-engine.json`:携带 `mci_system_setting`、`mci_user_external_identity`、默认设置和平台内置微服务。默认行必须使用 `InsertIfMissing + ConfigKey`,只补缺失,不覆盖 `ValueSource=Tenant` 的租户值或租户后来明确关闭的功能。小型平台启动微服务应以 `Source=NotIncluded + Build=DatabaseOnly + StorageMode=db` 随程序集交付并接受 256 文件/5MB、逐文件哈希和无源码门禁,使新租户在 HDFS 故障时仍能打开商城与恢复入口;普通应用安装、源码编辑和文件能力继续失败关闭,不得伪装成全平台健康。
64
+ - 批量任务已经以“一个应用”为外层持久化恢复单元。规模可控的小型官方包应在一个事务中完成,避免对同一包体按 8 个字段反复下载、解析和重新排队;超过字段、表、DDL、流程、随包数据或资产安全阈值的大包继续使用内部 checkpoint 分片。热更新发现旧版批量计划不含 `ApplicationType` 时,必须丢弃旧计划并重新盘点,不能继续安装历史计划中的社区应用。
65
+ - MySQL 宽表触发 65,535 字节行内上限时,只允许把不参与索引的 `varchar` 配置列无损提升为 `mediumtext`,并把类型覆盖持久化到后台任务 checkpoint;索引列和非行宽错误必须失败关闭。发布包对长连接串、密钥、回调地址、域名/白名单等字段应直接使用 `mediumtext`,同时更新 `DiyFields` 与建表 DDL,不能长期依赖安装时猜测。
66
+ - 卸载是破坏性操作,必须明确列出将删除/保留的资源、二次确认并优先软删除/归档业务数据。
67
+
68
+ ## 联邦商城源、公开范围与历史版本(强制)
69
+
70
+ - 每个主租户和子租户都可以发布自己的应用;应用行用 `IsPublic` 表达公开范围,缺省/历史空值按公开兼容。公开应用允许未登录来源读取和安装,私有应用只允许来源登录成功后的授权身份读取,列表、详情、版本接口都必须重复执行这一权限判断。
71
+ - 商城来源以 `ApiBase + OsClient` 唯一定位。添加来源先只读发现系统标题、验证码策略和公开应用数;需要私有应用时再登录。帐号、密码、Token 不能写浏览器配置或商城来源 JSON;密码只用于本次登录,长会话 Token 以 `MCP/Mobile` 非 PC 客户端签发,并由当前租户后端加密保存到 `mci_system_setting`,浏览器只持有不具备取密能力的凭据 Key。
72
+ - 后端来源代理必须固定已保存的 `ApiBase + OsClient`,拒绝过期 Token、访问密钥会话、非超级管理员、非 HTTPS 外网地址、重定向漂移和超限响应;Token 不得返回浏览器、日志、审计或应用包。退出登录同步删除服务端密文。
73
+ - 商城主页面统一承载应用市场、已安装、我发布的应用、安装离线包和来源管理,不能再通过独立菜单或路由割裂上下文。来源增删改启停逐项自动保存;来源管理、详情和复杂配置使用平台统一 `80%` 可拖动大圆角 Dialog,遮罩服从正向开关 `sys_config.FormMaskBlur`,缺失或 `0/false` 默认关闭毛玻璃。
74
+ - 每张应用卡必须显示预览图、公开范围、分类、最新版本、当前租户已安装版本及状态色。来源卡必须显示其公开数和当前授权可访问总数;平台官方发布节点只显示“平台官方应用源”身份标记,不显示安装、更新或重新安装操作。
75
+ - 安装可明确选择 `sys_microistore` 当前版本或 `mic_data_version` 中仍含完整包正文的历史快照;后台任务必须把 `StoreVersionId` 一直传到详情取包并把实际安装版本写回 `sys_microistoreversion`。回退旧版属于重新安装,不得静默换成最新版。
76
+ - 应用详情的版本选择必须服务端分页和搜索,默认每页不超过 20 条;当前版本固定置顶,历史版本只返回仍包含完整包正文的可安装状态。禁止用 `_PageSize:500` 或一次加载全部版本后在浏览器过滤。翻页、搜索与页大小切换都必须保持已选版本语义并显示总数。
77
+ - 商城详情、来源管理等 Teleport 弹层必须使用宿主级固定遮罩,毛玻璃覆盖完整可视区域;标题栏拖动按弹层真实尺寸限制四边,窗口缩放后重新限制,不能依赖固定像素最大位移或允许内容越出视口。
78
+ - “我发布的应用”只读取当前登录用户拥有的记录,可以包含草稿和构建失败项;普通商城列表只读取已发布项。两者必须在服务端按 Owner 和发布状态过滤,不能依赖浏览器过滤后再分页。
79
+
80
+ ## 发布版本与资源选择
81
+
82
+ - 发布器必须把用户请求的精确版本传给资产准备器,并断言 `RequestedVersion == Prepared.PackageVersion == AppPakcet.PackageInfo.Version`;版本不存在就失败,禁止静默改用最新版本。
83
+ - `SelectMenu`、`SelectTable`、`SelectApiEngine` 必须从当前发布包的显式选择持久化;不能读取商城行上一次保存的选择来决定本次包内容。
84
+ - 发布完成后同时回读商城版本行、包正文和构建资产,逐项核对版本、数量与 SHA-256;任一处漂移即发布失败。
85
+ - 官方内置前端应用只能有一个发布源码根。默认租户工作副本与受审计的独立 Git 源码仓库不能同时成为事实源;若使用独立仓库,必须提交一个发布契约并让构建、跨工程测试、所有程序集内置包共同读取它,正式发布还要证明源码根来自无未提交修改的 Git 提交。前端主包只提供通用宿主、诊断和恢复入口,不复制完整业务源码。HDFS/CDN 运行镜像必须回读到同一 `RuntimeManifestHash` 后才可启用,不能用较新的镜像静默覆盖较旧数据库包,也不能用较新的数据库包静默覆盖未验签镜像。
86
+ - `ScheduleJobs` 是一等包资源,必须在 `PostSchema` 之后独立安装、持久化 checkpoint 并回读运行状态;任务失败时不得写入成功版本。
87
87
 
88
88
  ## MCP 工作流
89
89
 
@@ -152,38 +152,38 @@ description: Microi 应用商城开发、打包、安装和升级规范。用于
152
152
  - 官网当前资源只是三方合并的一侧,允许暂时落后于本地发布候选。下载阶段只校验固定白名单、稳定资源身份、JSON 可解析性及服务端返回 SHA-256;不能用“必须已包含本地最新功能标记”的规则提前拒绝旧官网,否则会形成“官网不够新所以永远无法发布新版”的循环依赖。
153
153
  - 本地输入和三方合并后的最终候选必须继续执行最低版本、功能标记、内嵌逻辑副本一致性等严格校验;发布成功并按内容哈希回读一致后才能推进 `.resource-sync-base`,不能把放宽读取门误做成放宽发布门。
154
154
  - 应用包版本与平台发布版本分别单调递增。包正文需要写回而本地包版本、平台版本均未高于官网时,应基于官网包版本自动递增补丁号;内容无变化时不得递增,必须用连续两次同步验证第二次为零变更。
155
- - MCP 配置中的官方 API、`OsClient` 与 Token 文件是鉴权事实源,但编辑器可执行文件、插件版本目录和 `cwd` 都是易漂移的启动信息。发布器应保留鉴权配置、固定校验 `https://api.itdos.com + itdos`,并支持插件生成的稳定 `microi-cli-mcp.js` 或标准 `mcp-server.js` 入口;旧扩展配置再从同级最新已安装插件或当前工作区发现可信入口,统一使用正在运行发布脚本的 Node 启动。插件升级、Codex 插件化或旧目录清理不能再次阻塞后端发布。
155
+ - MCP 配置中的官方 API、`OsClient` 与 Token 文件是鉴权事实源,但编辑器可执行文件、插件版本目录和 `cwd` 都是易漂移的启动信息。发布器应保留鉴权配置、固定校验 `https://api.itdos.com + itdos`,并支持插件生成的稳定 `microi-cli-mcp.js` 或标准 `mcp-server.js` 入口;旧扩展配置再从同级最新已安装插件或当前工作区发现可信入口,统一使用正在运行发布脚本的 Node 启动。插件升级、Codex 插件化或旧目录清理不能再次阻塞后端发布。
156
156
  - Token 文件的新键固定为 `ApiBase|OsClient|OsClientType|OsClientNetwork` 四段身份;Type/Network 为空时仍保留空段。读取和回写必须先用四段精确键,再兼容旧版紧凑键;旧键在多环境配置下可能被有意保留且已经失效,禁止优先读取。自动化测试要覆盖“精确键已刷新、旧键仍过期”以及 type-only/network-only 不碰撞。
157
157
  - VS Code 的 SecretStorage 恢复 broker 必须使用确定性激活事件启动;不得只依赖大型工作区可能超时的递归 `workspaceContains`。签名密钥变化时旧 Token 本身不能以旧换新,必须由已激活 broker 使用本机 SecretStorage 静默重登并回写精确身份键。
158
- - 本地资源同步的官网读取、发布和发布后回读应使用同一个已校验的 `microi_itdos` MCP 链路;CI 无 MCP 时才允许凭显式 Token 使用 HTTP。V8 独立文件与应用包内嵌副本合并时,先把文件头说明和 `Version` 与可执行正文分离:两端独立升版不能算代码冲突,不同正文安全合成后应基于两端最高版本再升一版;只有同一段可执行逻辑出现不同实现才失败关闭。
159
- - 新增平台共享物理列时,除一次性版本门升级外,还要同步所有会快照该共享表的官方包 `PhysicalColumns`,让新安装和旧租户升级两条路径一致。`.resource-sync-base` 是上次官网回读的共同基线,不能与本地候选一起手工修改;基线可疑时先从官网只读修复,再执行三方合并、自动升包版本、正式发布和 SHA 回读。
160
- - 发布验收至少包含:定向合并测试、真实 `PublishBatch`、六项资源逐项 SHA-256 回读,以及立即执行第二次幂等重跑。任何一步失败都不得宣称官网已同步,也不得推进共同基线。
161
-
162
- ## 复盘:官网模板库误报平台应用可更新
163
-
164
- - 触发场景:官网 `sys_microistore` 的平台应用版本持续发布,但 `sys_microistoreversion` 仍保留旧安装版本;官网自身会显示“可更新”,从官网数据库复制出来的新租户也继承同一误报,尽管这些平台能力实际已经随官网主库维护完成。
165
- - 身份边界:只能在服务端同时满足 `OsClient=iTdos` 且当前节点私钥公钥部分与内嵌官方 License 公钥完全一致时执行。只使用同名租户、域名、配置开关或任意自建私钥都不得触发;客户租户的安装版本仍是其独立事实源。
166
- - 对齐规则:每次后端启动都在现有租户升级分布式租约内盘点 `ApplicationType=Platform + IsApprove=1` 的商城行,只处理 `Installed/Success/Succeeded/已安装` 的既有安装记录,按 `StoreId -> AppId -> 唯一 AppName` 匹配。只条件更新 `AppVersion/AppVersionInstall/PackageVersion`;稳定键仅在目标键未被其它安装记录占用时补齐。不得新增“已安装”记录、覆盖失败/异常状态、修改安装时间或删除重复历史行。
167
- - 分布式与验收:更新是确定值条件写入,节点中途退出后下次启动继续,第二次执行必须零更新;验收同时回读版本表三个字段,并执行官网商城列表接口,确认 `Outdated=0`、`Abnormal=0`。真实未安装应用仍应保留 `Uninstalled`,不能为了清空通知伪造成已安装。
168
-
169
- ## 复盘:共同基线已有引擎但官网内嵌副本缺失
170
-
171
- - 触发场景:本地 `app.microi.store.json`、独立接口脚本和 `.resource-sync-base` 都已有新引擎,但官网商城包尚未收录或被单侧删除;同步器在三方合并前强制读取官网内嵌代码,直接报“缺少接口引擎”,导致新版永远无法通过一键发布补到官网。
172
- - 根因:旧状态机只区分“共同基线不存在的首次新增”和“三端都存在的正常合并”,漏掉“共同基线已登记、官网副本缺失”的历史基线漂移;严格 getter 在合并前抛错,使已有的首次发布与逻辑副本修复规则没有机会运行。
173
- - 通用规则:只要副本映射仍属于当前发布契约,本地独立源码和内嵌副本能从共同基线安全合并,官网单独缺少内嵌引擎应视为不完整副本。JSON 合并前只从共同基线恢复该引擎的结构骨架;有官网独立文件时继续把它作为官网代码侧,无独立文件时把共同基线代码视为官网未修改,再执行正文三方合并并将结果写回内嵌副本。写回后必须按 `SysApiEngines.length` 重算 `PackageInfo.ApiEngineCount`。若共同基线引擎 Id 已被其它 Key 占用,或任意两侧同一代码位置实现冲突,仍必须失败关闭;不得通过覆盖/重建整个共同基线来掩盖问题。
174
- - 自动化检查:同时覆盖共同基线不存在的首次新增、共同基线存在但官网缺失且本地升级、官网内嵌缺失但官网独立源码升级、共同基线 Id 被其它 Key 占用四种状态;断言声明引擎数等于实际数组长度;再用真实 `microi_itdos` 只读资源重放,确认候选含目标引擎且独立源码与内嵌代码相同,正式发布后执行 SHA 回读和零变更幂等重跑。
175
-
176
- ## 复盘:老租户 NULL 数据阻止物理列收紧
158
+ - 本地资源同步的官网读取、发布和发布后回读应使用同一个已校验的 `microi_itdos` MCP 链路;CI 无 MCP 时才允许凭显式 Token 使用 HTTP。V8 独立文件与应用包内嵌副本合并时,先把文件头说明和 `Version` 与可执行正文分离:两端独立升版不能算代码冲突,不同正文安全合成后应基于两端最高版本再升一版;只有同一段可执行逻辑出现不同实现才失败关闭。
159
+ - 新增平台共享物理列时,除一次性版本门升级外,还要同步所有会快照该共享表的官方包 `PhysicalColumns`,让新安装和旧租户升级两条路径一致。`.resource-sync-base` 是上次官网回读的共同基线,不能与本地候选一起手工修改;基线可疑时先从官网只读修复,再执行三方合并、自动升包版本、正式发布和 SHA 回读。
160
+ - 发布验收至少包含:定向合并测试、真实 `PublishBatch`、六项资源逐项 SHA-256 回读,以及立即执行第二次幂等重跑。任何一步失败都不得宣称官网已同步,也不得推进共同基线。
161
+
162
+ ## 复盘:官网模板库误报平台应用可更新
163
+
164
+ - 触发场景:官网 `sys_microistore` 的平台应用版本持续发布,但 `sys_microistoreversion` 仍保留旧安装版本;官网自身会显示“可更新”,从官网数据库复制出来的新租户也继承同一误报,尽管这些平台能力实际已经随官网主库维护完成。
165
+ - 身份边界:只能在服务端同时满足 `OsClient=iTdos` 且当前节点私钥公钥部分与内嵌官方 License 公钥完全一致时执行。只使用同名租户、域名、配置开关或任意自建私钥都不得触发;客户租户的安装版本仍是其独立事实源。
166
+ - 对齐规则:每次后端启动都在现有租户升级分布式租约内盘点 `ApplicationType=Platform + IsApprove=1` 的商城行,只处理 `Installed/Success/Succeeded/已安装` 的既有安装记录,按 `StoreId -> AppId -> 唯一 AppName` 匹配。只条件更新 `AppVersion/AppVersionInstall/PackageVersion`;稳定键仅在目标键未被其它安装记录占用时补齐。不得新增“已安装”记录、覆盖失败/异常状态、修改安装时间或删除重复历史行。
167
+ - 分布式与验收:更新是确定值条件写入,节点中途退出后下次启动继续,第二次执行必须零更新;验收同时回读版本表三个字段,并执行官网商城列表接口,确认 `Outdated=0`、`Abnormal=0`。真实未安装应用仍应保留 `Uninstalled`,不能为了清空通知伪造成已安装。
168
+
169
+ ## 复盘:共同基线已有引擎但官网内嵌副本缺失
170
+
171
+ - 触发场景:本地 `app.microi.store.json`、独立接口脚本和 `.resource-sync-base` 都已有新引擎,但官网商城包尚未收录或被单侧删除;同步器在三方合并前强制读取官网内嵌代码,直接报“缺少接口引擎”,导致新版永远无法通过一键发布补到官网。
172
+ - 根因:旧状态机只区分“共同基线不存在的首次新增”和“三端都存在的正常合并”,漏掉“共同基线已登记、官网副本缺失”的历史基线漂移;严格 getter 在合并前抛错,使已有的首次发布与逻辑副本修复规则没有机会运行。
173
+ - 通用规则:只要副本映射仍属于当前发布契约,本地独立源码和内嵌副本能从共同基线安全合并,官网单独缺少内嵌引擎应视为不完整副本。JSON 合并前只从共同基线恢复该引擎的结构骨架;有官网独立文件时继续把它作为官网代码侧,无独立文件时把共同基线代码视为官网未修改,再执行正文三方合并并将结果写回内嵌副本。写回后必须按 `SysApiEngines.length` 重算 `PackageInfo.ApiEngineCount`。若共同基线引擎 Id 已被其它 Key 占用,或任意两侧同一代码位置实现冲突,仍必须失败关闭;不得通过覆盖/重建整个共同基线来掩盖问题。
174
+ - 自动化检查:同时覆盖共同基线不存在的首次新增、共同基线存在但官网缺失且本地升级、官网内嵌缺失但官网独立源码升级、共同基线 Id 被其它 Key 占用四种状态;断言声明引擎数等于实际数组长度;再用真实 `microi_itdos` 只读资源重放,确认候选含目标引擎且独立源码与内嵌代码相同,正式发布后执行 SHA 回读和零变更幂等重跑。
175
+
176
+ ## 复盘:老租户 NULL 数据阻止物理列收紧
177
177
 
178
178
  - 触发场景:商城应用包把既有字段从可空升级为 `NOT NULL DEFAULT ...`,老租户的物理列已经存在,但历史记录仍为 `NULL`;导入器直接执行 `ALTER TABLE ... MODIFY COLUMN ... NOT NULL` 时,MySQL 报 `Invalid use of NULL value`,整个安装分片失败。
179
179
  - 根因:物理列同步只比较类型、可空性、默认值和注释,没有在收紧可空性前迁移存量数据。列默认值只影响后续写入,不会自动修复既有 `NULL`。
180
180
  - 通用规则:当包要求 `NOT NULL`、目标列仍可空且存在历史 `NULL` 时,必须先用包内明确声明的默认值参数化回填,再执行列约束变更;包未声明默认值时失败关闭并报告影响行数,禁止猜测业务值。该步骤必须可重复执行,并允许多节点并发重试后得到同一结果。
181
- - 自动化检查:构造可空旧列及多条 `NULL` 行,断言导入器按“统计 NULL → 参数化回填 → `MODIFY ... NOT NULL`”顺序执行;覆盖字符串、整数、零行、缺失默认值、重复执行,以及商城包中全部发布协议状态字段。
182
-
183
- ## 复盘:应用新增菜单未自动授予系统管理员完整权限
184
-
185
- - 触发场景:应用首次安装或版本更新新增了 `sys_menu`,菜单数据已经存在,但系统管理员看不到入口或只能执行部分按钮;再次人工到角色管理中勾选后才恢复。
186
- - 根因:安装器只导入菜单,没有在同一事务内写入 `sys_rolelimit`;历史补丁又把单个管理员角色 Id 和五项旧权限硬编码,只能修复某个菜单,遗漏 `Read`、自定义按钮及其它 `Level >= 9999` 管理员角色。
187
- - 通用规则:安装器只对本次真正新增或从删除状态重新引入的菜单自动授权,不扩大既有菜单的客户权限策略。目标角色必须从当前租户实时读取全部有效 `sys_role.Level >= 9999` 记录;基础权限固定为 `Read/Add/Edit/Del/Export/Import`,并合并菜单 `MoreBtns/ExportMoreBtns/BatchSelectMoreBtns/PageBtns/PageTabs/FormBtns` 中每个按钮的 `Id + Name`,不得加入 `NoDetail/NoSearch` 这类限制权限。
188
- - 幂等与失败边界:已有 `sys_rolelimit` 只能合并、不得删除历史自定义权限;新增行使用“租户 + 角色 + 菜单”的确定性 Id,并在并发主键冲突后重新回读合并。找不到系统管理员、查询失败或任一权限写入失败必须让整个安装事务回滚,不能出现“菜单成功但管理员无权”的半成品。通过 FormEngine 写入以触发共享授权缓存失效。
189
- - 自动化检查:覆盖多个系统管理员、已有部分权限、自定义按钮既有 JSON 字符串也有数组、删除菜单恢复、重复安装零新增、两个节点同时插入后合并,以及既有菜单更新不自动扩权;发布门同时校验独立导入器与商城包内嵌副本都包含该能力。
181
+ - 自动化检查:构造可空旧列及多条 `NULL` 行,断言导入器按“统计 NULL → 参数化回填 → `MODIFY ... NOT NULL`”顺序执行;覆盖字符串、整数、零行、缺失默认值、重复执行,以及商城包中全部发布协议状态字段。
182
+
183
+ ## 复盘:应用新增菜单未自动授予系统管理员完整权限
184
+
185
+ - 触发场景:应用首次安装或版本更新新增了 `sys_menu`,菜单数据已经存在,但系统管理员看不到入口或只能执行部分按钮;再次人工到角色管理中勾选后才恢复。
186
+ - 根因:安装器只导入菜单,没有在同一事务内写入 `sys_rolelimit`;历史补丁又把单个管理员角色 Id 和五项旧权限硬编码,只能修复某个菜单,遗漏 `Read`、自定义按钮及其它 `Level >= 9999` 管理员角色。
187
+ - 通用规则:安装器只对本次真正新增或从删除状态重新引入的菜单自动授权,不扩大既有菜单的客户权限策略。目标角色必须从当前租户实时读取全部有效 `sys_role.Level >= 9999` 记录;基础权限固定为 `Read/Add/Edit/Del/Export/Import`,并合并菜单 `MoreBtns/ExportMoreBtns/BatchSelectMoreBtns/PageBtns/PageTabs/FormBtns` 中每个按钮的 `Id + Name`,不得加入 `NoDetail/NoSearch` 这类限制权限。
188
+ - 幂等与失败边界:已有 `sys_rolelimit` 只能合并、不得删除历史自定义权限;新增行使用“租户 + 角色 + 菜单”的确定性 Id,并在并发主键冲突后重新回读合并。找不到系统管理员、查询失败或任一权限写入失败必须让整个安装事务回滚,不能出现“菜单成功但管理员无权”的半成品。通过 FormEngine 写入以触发共享授权缓存失效。
189
+ - 自动化检查:覆盖多个系统管理员、已有部分权限、自定义按钮既有 JSON 字符串也有数组、删除菜单恢复、重复安装零新增、两个节点同时插入后合并,以及既有菜单更新不自动扩权;发布门同时校验独立导入器与商城包内嵌副本都包含该能力。