@microi.net/cli 5.2.3 → 5.2.4

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.
@@ -80,9 +80,10 @@ UniApp 使用 Vue 3 + TypeScript 的官方 Vite 工具链,并同时遵守 `mic
80
80
  2. 依次执行类型检查、单元测试、生产构建和产物静态扫描。
81
81
  3. 检查 `dist/build` 不含源码、Token、密钥、localhost、source map 或陈旧 chunk。
82
82
  4. 同步私有源码,再流式发布公有构建目录;源码同步失败不得继续发布。发布前回读并冻结应用的 `CurrentVersion` 与 `AppVersion`,stage 只上传不可变版本资产,finalize 必须同时提交 `ExpectedCurrentVersion` 与 `ExpectedAppVersion` 做 compare-and-set;缺一项、状态漂移或回读不一致都停止,不能自动覆盖较新发布。
83
- 5. Web/UniApp 使用 `/{OsClient}/ai-app-publish/{AppKey}/index.html`;MicroService 使用 `/micro-app/{OsClient}/{AppKey}/index.html`。不要因技术栈相同而混淆运行类型。
84
- 6. 官网、二维码、分享链接和商城“立即体验”只能使用不含 `/releases/`、`/requests/`、`/versions/` 与语义版本号的稳定当前入口;不得使用 `SharedPublicRuntime.EntryUrl` 或发布结果中的不可变版本 URL。固定入口必须以代理或全屏加载壳保持浏览器地址不变,不能用 30x、`meta refresh` 或 `location.replace` 把地址栏跳到版本产物。
85
- 7. `SharedPublicRuntime.EntryUrl` `/versions/{Version}/index.html` 仅用于历史记录、回滚、摘要校验与审计。回读应用、版本、active 文件清单和 SHA-256;旧清单文件只能可逆归档,不能删除。再分别直接请求稳定当前入口、不可变版本入口及主要 JS/CSS,并断言前者完成加载后地址栏仍不含版本段。
83
+ 5. 每次创建、修改、升级或重新发布 AI 应用,必须在任何源码同步、stage、finalize 或商城制包之前,为目标精确 `AppVersion` 写入 `sys_microistore_changelog`。日志的 `StoreId / Version / Title / ChangeType / Content / ReleaseTime` 必须完整;发布工具显式传入含义一致且非空的 `changeSummary`,发布后同时回读商城子表与 `mci_ai_app_version.ChangeSummary`。缺日志或版本不一致必须停止发布。
84
+ 6. Web/UniApp 使用 `/{OsClient}/ai-app-publish/{AppKey}/index.html`;MicroService 使用 `/micro-app/{OsClient}/{AppKey}/index.html`。不要因技术栈相同而混淆运行类型。
85
+ 7. 官网、二维码、分享链接和商城“立即体验”只能使用不含 `/releases/`、`/requests/`、`/versions/` 与语义版本号的稳定当前入口;不得使用 `SharedPublicRuntime.EntryUrl` 或发布结果中的不可变版本 URL。固定入口必须以代理或全屏加载壳保持浏览器地址不变,不能用 30x、`meta refresh` `location.replace` 把地址栏跳到版本产物。
86
+ 8. `SharedPublicRuntime.EntryUrl` 和 `/versions/{Version}/index.html` 仅用于历史记录、回滚、摘要校验与审计。回读应用、版本、active 文件清单和 SHA-256;旧清单文件只能可逆归档,不能删除。再分别直接请求稳定当前入口、不可变版本入口及主要 JS/CSS,并断言前者完成加载后地址栏仍不含版本段。
86
87
 
87
88
  ## 完成定义
88
89
 
@@ -78,7 +78,7 @@
78
78
  | 组件 | 推荐类型 | 配置项 |
79
79
  | --- | --- | --- |
80
80
  | `RichText` | `mediumtext` | 富文本内容,图片上传遵循平台上传配置。 |
81
- | `CodeEditor` | `mediumtext` | `CodeEditor.Height`。 |
81
+ | `CodeEditor` | `mediumtext` | `CodeEditor.Height`;`CodeEditor.DisplayMode=Inline/Dialog`,配置项很多或同页多个代码字段时优先 `Dialog`。 |
82
82
  | `JsonTable` | `mediumtext` | JSON 表格展示/编辑,保存结构化 JSON;配置必须写在 `Config.JsonTable`。 |
83
83
  | `ImgUpload` | `mediumtext` | `ImgUpload.Limit`、`Multiple`、`Tips`、`MaxCount`、`ShowFileList`、`Preview`、`MaxSize`。 |
84
84
  | `FileUpload` | `mediumtext` | `FileUpload.Limit`、`Multiple`、`Tips`、`MaxCount`、`ShowFileList`、`MaxSize`。 |
@@ -36,7 +36,7 @@
36
36
  | `StaticText` | 静态文本 | 不承载业务状态 |
37
37
  | `Html` | 可信 HTML 展示 | 必须净化,不拼接不可信内容 |
38
38
  | `RichText` | 富文本 | `mediumtext`;输出需净化 |
39
- | `CodeEditor` | 代码/JSON/SQL 编辑 | `mediumtext`;通常 `FormWidth=24` |
39
+ | `CodeEditor` | 代码/JSON/SQL 编辑 | `mediumtext`;通常 `FormWidth=24`;长配置表单使用 `Config.CodeEditor.DisplayMode=Dialog`,默认只渲染“编辑代码(N字)”按钮;代码工作台可用 `Inline` |
40
40
  | `JsonTable` | JSON 表格 | `mediumtext`;定义结构与大小上限 |
41
41
 
42
42
  ## 文件与高级输入
@@ -104,6 +104,7 @@ AppKey 稳定且只含安全字符。`microi.routes.json` 是页面事实源,
104
104
  - 创建/更新元数据:`microi_create_microservice`。
105
105
  - 同步私有源码:`microi_sync_microservice_source`;本地工程必须优先传 `directory`,不构造 Base64 文件数组。
106
106
  - 真实编译目录优先 `microi_publish_application_directory_stream` 流式发布。
107
+ - 每次创建、修改、升级或重新发布微服务,必须先为目标精确 `AppVersion` 在 `sys_microistore_changelog` 写入完整日志,再同步源码、stage、finalize 或制作商城包。日志必须关联真实 `StoreId`,包含 `Title / ChangeType / Content / ReleaseTime`;流式发布显式传入与日志含义一致的非空 `changeSummary`。发布后同时回读商城日志、`mci_ai_app_version.ChangeSummary` 与包内 `PackageInfo.ChangeLog`;缺失或版本不一致必须失败关闭。
107
108
  - 发布动作必须明确区分两种模式:默认“源码+编译产物”先把完整工程同步到私有桶并逐文件回读 SHA-256,再把 `dist` 流式发布到公有桶;显式“仅编译产物”只更新公有桶,必须在界面中告知其他用户仍会拉取上一次私有源码,禁止暗示源码已同步。
108
109
  - 私有源码同步使用 `ReplacePrivateSourceOnly` 精确清理过期源码;兼容调用可以继续接受 `replace`,但实现不得用旧式全表 `Replace=true` 删除同一应用的公有运行产物元数据。
109
110
  - `mci_ai_app_file` 同时存在私有源码和公有编译产物。源码拉取/差异比较必须优先按 `StorageScope=PublicBuildStream|PublicBuildStreamArchived|PublicBuildOnly` 排除公有产物,并保留旧数据中 `HdfsPath == PublishHdfsPath` 的兼容判断;不能仅靠两个路径相等识别,否则版本路径与稳定别名不同的流式产物会被误读成私有源码。
@@ -150,7 +150,7 @@ return {
150
150
  | `NumberFormat/HeaderStyle/Style` | 数字格式与列级样式 |
151
151
 
152
152
  <!-- /microi-progressive:chunk -->
153
- <!-- microi-progressive:chunk id=v8-export-import-003 sha256=8c2868406d663d51bbd479c12b052b70ffa1014cc4ec4186b8dcecd0e5a3105b -->
153
+ <!-- microi-progressive:chunk id=v8-export-import-003 sha256=75977093346f025e91041b36bdb7887e2cacee854800c1f43e407e8fc037a166 -->
154
154
  ## 解析上传的 Excel(导入)
155
155
 
156
156
  ```javascript
@@ -160,23 +160,26 @@ if (!filesByteBase64) return { Code: 0, Msg: '请上传 Excel 文件' };
160
160
 
161
161
  var base64 = Object.values(filesByteBase64)[0];
162
162
 
163
- // 解析第一张工作表为对象数组
164
- var parsed = V8.Office.ExcelToList({
165
- FileByteBase64: base64,
166
- SheetIndex: 0
163
+ // 可直接解析旧的首行表头模板
164
+ var parsed = V8.Office.ExcelToList({
165
+ FileByteBase64: base64,
166
+ SheetIndex: 0
167
167
  });
168
168
  if (parsed.Code !== 1) return parsed;
169
169
 
170
- var dataList = parsed.Data; // [{ 列标题: 值, ... }, ...]
170
+ var dataList = parsed.Data; // [{ 列标题: 值, ... }, ...]
171
171
  return { Code: 1, Data: dataList, DataCount: dataList.length };
172
172
  ```
173
173
 
174
+ `ExcelToList` 的增强参数为 `HeaderStartRow/HeaderEndRow/DataStartRow/DataEndRow/Columns/MaxDataRows/MaxColumns`。除 `SheetIndex` 和 `Columns[].ColumnIndex` 从 `0` 开始外,行号都从 `1` 开始;传增强范围后每行带 `_ExcelRow`。参数全省略时继续兼容“首行表头、第二行开始数据”。
175
+
174
176
  ### 固定版式模板与后台自定义导入
175
177
 
176
- 默认导入适合首行即字段标题的标准表格。多行表头、合并单元格、项目名称位于固定单元格、或需按规格/材质查询存货等模板,页面按钮使用 `V8.OpenImportDialog({...})` 声明工作表、单元格和列映射;平台弹层负责浏览器解析、后台任务提交、真实进度轮询与结果呈现。
178
+ 通用【导入】和 `V8.OpenImportDialog` 共用智能导入弹层:默认宽度 `80%`,选择文件后自动识别工作表、单行/多级合并表头、首条与末条数据行和字段映射;先按每页 `15` 条预览,用户确认后才写入。低可信度时必须允许用户人工指定表头/数据起止行和逐列映射。模板顶部图片、标题、说明文字以及 A 列为空的数据行都不能破坏识别。
177
179
 
178
- - 页面 V8 只声明 `ApiEngineKey`、`Workbook.Cells/Columns/DataStartRow/DataEndRow/KeyField`,不得拼上传 DOM、传完整工作簿 Base64 或自行轮询。
179
- - 后台接口引擎从 `V8.Param._ImportRowsJson` 和 `_ImportMetaJson` 取值,必须重做模板、权限、字段、唯一性和状态校验。
180
+ - 页面 V8 可只声明 `ApiEngineKey`;`Workbook.Cells/Columns/HeaderStartRow/HeaderEndRow/DataStartRow/DataEndRow/KeyField` 均为模板提示或固定约束,不传时自动识别。不得拼上传 DOM、传完整工作簿 Base64 或自行轮询。
181
+ - `V8.OpenImportDialog` 后台接口引擎从 `V8.Param._ImportRowsJson` 和 `_ImportMetaJson` 取值;必须重做模板、权限、字段、唯一性和状态校验。
182
+ - 菜单【导入接口替换】仍接收原始文件 `V8.FilesByteBase64`,并新增 `_ImportMetaJson`。接口引擎必须把元数据里的 `SheetIndex/HeaderStartRow/HeaderEndRow/DataStartRow/DataEndRow/Columns` 传给 `V8.Office.ExcelToList`,由服务端按同一范围重读原文件,不能只信任浏览器预览,也不能固定读取第一行。
180
183
  - 先校验全部行再写入;接口引擎返回 `Code != 1` 时依靠平台事务整体回滚,禁止手动 Commit/Rollback。
181
184
  - 用 `V8.Method.UpdateBackgroundTask({Current,Total,Msg,Log})` 上报真实校验/写入工作量;未知总量保持不确定进度,不伪造百分比。
182
185
  - 业务幂等键使用后台任务 Id 或明确的导入操作 Id;重试前回读批次,避免重复写入。
@@ -32,7 +32,7 @@ V8.ClientModel // OsClientModel 的兼容别名,同样是脱敏副本
32
32
  V8.SysConfig // 当前租户系统配置根对象;不存在 PublicSettings 属性
33
33
  ```
34
34
 
35
- 前端 V8 的 `V8.SysConfig` 是匿名 `GetSysConfig` 的独立脱敏副本,`mci_system_setting` 中允许公开的普通值直接平铺到根对象;不会暴露 `ClientSecrets`、`GlobalServerV8Code` 或疑似凭据字段。后端接口引擎与后端 V8 事件的 `V8.SysConfig` 是当前租户完整、独立的 `sys_config`,并把全部启用的租户设置(含后端解密后的 Secret)平铺到根对象。两端都不存在 `PublicSettings` 包装层。后端可使用 Secret,但严禁返回前端、写日志或写审计。子租户显式传其它 `OsClient` 仍会被强制改回当前租户。
35
+ 前端 V8 的 `V8.SysConfig` 是匿名 `GetSysConfig` 的独立脱敏 `sys_config` 副本;`mci_system_setting` 的任何记录都不会进入浏览器。后端接口引擎与后端 V8 事件的 `V8.SysConfig` 包含当前租户完整、独立的 `sys_config`,后端私密设置统一位于 `V8.SysConfig.ServerPrivateSettings`,其中 Secret 由可信后端解密。两端都不存在 `PublicSettings` 包装层。后端可使用 Secret,但严禁返回前端、写日志或写审计。子租户显式传其它 `OsClient` 仍会被强制改回当前租户。
36
36
 
37
37
  ### V8.OsClientModel 常用字段
38
38
 
@@ -41,7 +41,7 @@ V8.OsClientModel.SysTitle // 租户系统标题
41
41
  V8.OsClientModel.DbType // 非敏感数据库类型
42
42
  V8.OsClientModel.HDFS // 'Aliyun' / 'MinIO' / 'S3'
43
43
  V8.OsClientModel.AliOssPublicDomain // 可公开的文件域名
44
- // 当前租户自行扩展的业务字段只作存量兼容;新增配置使用 mci_system_setting
44
+ // 当前租户自行扩展的业务字段只作存量兼容;新增公开配置使用 sys_config,后端私密参数使用 mci_system_setting
45
45
 
46
46
  // 以下基础设施字段不会注入 V8:
47
47
  // DbConn / DbReadConn / AuthSecret
@@ -55,7 +55,7 @@ V8.OsClientModel.AliOssPublicDomain // 可公开的文件域名
55
55
 
56
56
  - 所有可变业务逻辑默认必须由接口引擎编排,包括但不限于租户开通、开库、初始化、归属修复、官网个人中心、付费额度等 SaaS 业务流程。C# 后端只暴露原子 V8 能力,例如建库、导入空库模板、复制 `sys_config`、刷新 SaaS 缓存、补偿回滚、字段兜底等;不要把可变业务分支写死到 Controller 或 `TenantProvisioningService` 这类后端定制代码里。接口引擎缺少能力时,优先扩展 `V8.Method`/V8 引擎原子函数,再由接口引擎调用。
57
57
  - 主租户由运行环境决定:优先读取环境变量 `OsClient`,其次读取 `appsettings.json` 的 `AppSettings:OsClient`。只有这条主租户 `sys_osclients` 数据中的平台级字段会作为全局配置生效。
58
- - 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` 节点或动态名称的环境变量读取。节点身份由平台自动生成。
58
+ - 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` 节点或动态名称的环境变量读取。节点身份由平台自动生成。
59
59
  - `ASPNETCORE_*`、`DOTNET_*` 仅用于 .NET 宿主;构建、安装、测试、MCP、发布脚本可使用自身进程变量,但 API 生产代码不得把它们当业务配置。新增 SaaS 运行字段必须配套独立或既有 Tab、幂等升级、缓存刷新、敏感字段脱敏、子租户不继承和源码扫描测试。
60
60
  - 文件上传的租户业务开关与额度按“当前租户 `sys_osclients` → 代码默认值”解析;平台固定灾难保护、HTTP/Multipart/Form 和反向代理上限不可由租户覆盖,也不要求安装者维护额外上传环境变量。
61
61
  - 类似 MQTT 端口、PressureGuard、V8Limits、OrmLimits、StartupLimits、SecurityGuard 这类影响整进程资源的配置,不能让每个子租户各自抬高全局上限。子租户同名隔离字段只能降低自己的并发、等待时间或资源额度,用于隔离弱租户、试用租户或异常租户。
@@ -147,15 +147,16 @@ var erpUrl = (V8.OsClientNetwork === 'Intranet')
147
147
  // ❌ 危险:密钥写在代码里,所有租户共用,无法独立轮换
148
148
  var ak = 'AKIDxxxxxxxx';
149
149
 
150
- // ✅ 普通业务值:每个租户在 mci_system_setting 动态维护
151
- var loginName = V8.SysConfig['Login.Gitee.Name'];
150
+ // ✅ 浏览器需要判断的开关:使用 sys_config 实体字段
151
+ var giteeEnabled = V8.SysConfig.GiteeLoginEnabled === 1;
152
152
 
153
153
  // ✅ 后端 V8 可读取当前租户 Secret 并直接调用供应商
154
- var secret = V8.SysConfig['Login.Gitee.ClientSecret'];
154
+ var privateSettings = V8.SysConfig.ServerPrivateSettings || {};
155
+ var secret = privateSettings['Login.Gitee.ClientSecret'];
155
156
  // 禁止 return secret、console.log(secret) 或写入前端可读字段。
156
157
  ```
157
158
 
158
- > `mci_system_setting` 位于每个租户自己的数据库。普通设置可逐条动态公开并直接平铺到前端 `V8.SysConfig`;Secret 保存认证密文,只在后端 V8 的当前租户 `V8.SysConfig` 中解密使用。前端 V8、普通 FormEngine HTTP、匿名/访问密钥会话不能读取 Secret,后端 V8 也不能获得通用解密器。`sys_osclients` 自定义业务字段只保留存量兼容;共享基础设施字段由服务端强制移除,不能用自定义同义字段绕过安全代理。
159
+ > `mci_system_setting` 位于每个租户自己的数据库,只保存不能公开或仅供后端执行的配置;普通值与 Secret 都不会下发浏览器。Secret 保存认证密文,只在后端 V8 的当前租户 `ServerPrivateSettings` 中解密使用。能力开关和入口显示必须建成 `sys_config` 实体字段,禁止通过 `IsPublic` 或其它运行时勾选把私密记录公开。前端 V8、普通 FormEngine HTTP、匿名/访问密钥会话不能读取私密设置,后端 V8 也不能获得通用解密器。`sys_osclients` 自定义业务字段只保留存量兼容;共享基础设施字段由服务端强制移除,不能用自定义同义字段绕过安全代理。
159
160
 
160
161
  ## 用户扩展字段访问(同理)
161
162
 
@@ -15,7 +15,9 @@ description: Microi V8 安全指南。用于审查 DiyToken 与权限、可逆
15
15
  <!-- microi-progressive:chunk id=v8-security-000 sha256=0346bd9ca3fe98dd2b589d1777aa1e55cd24cf7dedc69ee65d4ca91461db7dee -->
16
16
  ## 0. 租户动态系统设置与密钥边界
17
17
 
18
- 第三方密钥(微信、支付宝、OpenAI、阿里云、ERP、SMTP)**禁止**硬编码在 V8 代码或前端。公开的租户配置必须建成当前租户 `sys_config` 的实体字段;敏感或仅供后端使用的租户业务配置保存到 `mci_system_setting`。数据库、Redis、MongoDB、MinIO、MQ 等部署控制面仍由主库 `sys_osclients` 托管,子租户不能修改。
18
+ 第三方密钥(微信、支付宝、OpenAI、阿里云、ERP、SMTP)**禁止**硬编码在 V8 代码或前端。公开的租户配置必须建成当前租户 `sys_config` 的实体字段;敏感或仅供后端使用的租户业务配置保存到 `mci_system_setting`。数据库、Redis、MongoDB、MinIO、MQ 等部署控制面仍由主库 `sys_osclients` 托管,子租户不能修改。
19
+
20
+ 能力是否启用、入口是否显示、公开交互模式等 Bool/Enum 配置即使属于登录或第三方集成,也必须放在 `sys_config`;API Key、ClientSecret、RP ID、Origin、Issuer、Scope、供应商地址等后端参数才放在 `mci_system_setting`。禁止给同一个新配置双写两张表。迁移旧开关时采用“新 `sys_config` 显式值 → 旧私密 Key → 存量安全默认”的只读回退,并从私密设置的列表、保存和删除入口移除旧 Key。
19
21
 
20
22
  ```javascript
21
23
  // ✅ 浏览器/前端 V8 只读取 sys_config 的浏览器安全投影