@microi.net/cli 6.2.0 → 6.2.2
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/assets/build-meta.json +5 -5
- package/cordis.patch.yml +1 -1
- package/package.json +1 -1
- package/scripts/mcp-server.js +142 -117
- package/scripts/microi-cli.js +54 -54
- package/scripts/microi-skills.meta.json +250 -238
- package/skills/.microi-skills-version.json +2 -2
- package/skills/.progressive-disclosure-manifest.json +69 -38
- package/skills/README.md +1 -1
- package/skills/microi-client-frontend/SKILL.md +20 -14
- 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 +9 -1
- package/skills/microi-codex/SKILL.md +2 -0
- package/skills/microi-datasource-mapping/SKILL.md +5 -0
- package/skills/microi-db-schema/references/form-component-options.md +7 -0
- package/skills/microi-deployment/SKILL.md +3 -3
- package/skills/microi-deployment/references/deployment-matrix.md +1 -1
- package/skills/microi-docs-coverage/references/capability-map.md +6 -6
- package/skills/microi-form-engine/SKILL.md +21 -3
- package/skills/microi-form-engine/references/business-numbering.md +70 -0
- package/skills/microi-form-engine/references/component-catalog.md +4 -0
- package/skills/microi-form-engine/references/component-config-index.md +359 -0
- package/skills/microi-form-engine/references/data-source-events.md +7 -1
- package/skills/microi-form-engine/references/form-generation-quality.md +160 -0
- package/skills/microi-system-delivery/SKILL.md +7 -0
- package/skills/microi-system-delivery/references/delivery-pitfalls.md +5 -0
- package/skills/microi-uniapp-frontend/SKILL.md +3 -1
- package/skills/microi.v8.js +6 -4
- package/skills/module-engine/SKILL.md +8 -0
- package/skills/scripts/sync-embedded-skills.mjs +13 -0
- package/skills/uniapp-mall-assets/SKILL.md +3 -0
- package/skills/v8-file-upload/SKILL.md +7 -3
- package/skills/v8-file-upload/references/hotspot-offload-operations.md +18 -0
- 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 +7 -1
- package/skills/v8-frontend-events/SKILL.md +14 -6
- package/skills/v8-image-processing/SKILL.md +13 -2
- package/skills/v8-image-processing/references/api-reference.md +49 -3
- package/skills/v8-security/references/progressive-02-7-/346/227/245/345/277/227/350/256/260/345/275/225.md +6 -1
- package/skills/v8-utilities/references/server-api-index.md +1 -0
- package/skills/vision-engine/SKILL.md +12 -3
- package/skills/vision-engine/references/video-timeline.md +42 -0
package/skills/microi.v8.js
CHANGED
|
@@ -569,7 +569,7 @@ function installDatePrototypeCompat() {
|
|
|
569
569
|
}
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
-
// BEGIN GENERATED PUBLIC RESOURCE ROUTER; source SHA256
|
|
572
|
+
// BEGIN GENERATED PUBLIC RESOURCE ROUTER; source SHA256 94e9f239a70d003f6513a205d02e5d3dcaf3e80268bb3735523047949518ce9a
|
|
573
573
|
const createSdkPublicResourceClient = (() => {
|
|
574
574
|
// 公有资源路由的纯校验器与实际消费者桥接;私有分支继续走既有授权接口。
|
|
575
575
|
const HASH = /^[a-f0-9]{64}$/;
|
|
@@ -583,10 +583,10 @@ function key(value) {
|
|
|
583
583
|
return value;
|
|
584
584
|
}
|
|
585
585
|
const encodeKey = value => value.split('/').map(encodeURIComponent).join('/');
|
|
586
|
-
function plainBase(value, originOnly = false) {
|
|
586
|
+
function plainBase(value, originOnly = false, legacyPrimary = false) {
|
|
587
587
|
if (typeof value !== 'string' || /[\\%?#@\u0000-\u0020\u007f]/.test(value)) throw Error('InvalidPublicBinding');
|
|
588
588
|
const parsed = new URL(value);
|
|
589
|
-
if (parsed.protocol !== 'https:' || parsed.username || parsed.password || parsed.search || parsed.hash
|
|
589
|
+
if ((parsed.protocol !== 'https:' && !(legacyPrimary && parsed.protocol === 'http:')) || parsed.username || parsed.password || parsed.search || parsed.hash
|
|
590
590
|
|| (originOnly && parsed.pathname !== '/')) throw Error('InvalidPublicBinding');
|
|
591
591
|
return value.replace(/\/+$/, '');
|
|
592
592
|
}
|
|
@@ -617,7 +617,9 @@ function legacyPublicFallback(input, binding) {
|
|
|
617
617
|
const rawKey = decoratedAt < 0 ? relative : relative.slice(0, decoratedAt);
|
|
618
618
|
const suffix = decoratedAt < 0 ? '' : relative.slice(decoratedAt);
|
|
619
619
|
const objectKey = key(rawKey.split('/').map(part => decodeURIComponent(part)).join('/'));
|
|
620
|
-
|
|
620
|
+
// Preserve the tenant's existing HTTP FileServer only for the original
|
|
621
|
+
// public fallback. Verified backup/alias bindings remain HTTPS-only.
|
|
622
|
+
return plainBase(binding?.primaryBase, false, true) + '/' + encodeKey(objectKey) + suffix;
|
|
621
623
|
} catch { return ''; }
|
|
622
624
|
}
|
|
623
625
|
function identify(input, binding) {
|
|
@@ -136,6 +136,11 @@ HTTP 成功或菜单字段非空不足以证明统计有效。
|
|
|
136
136
|
|
|
137
137
|
## AI 模块视觉交付门禁(强制)
|
|
138
138
|
|
|
139
|
+
涉及编号、长串编码或来源/去向时,读取
|
|
140
|
+
[业务编号与追溯契约](../microi-form-engine/references/business-numbering.md)。
|
|
141
|
+
默认采用业务名称配业务编号,正常 Code 不按字段名隐藏;外部/历史编码保持来源映射,
|
|
142
|
+
真实追溯核对目标菜单、记录和权限,不能只给文字加蓝色。显式布局与隐藏配置先回读再合并。
|
|
143
|
+
|
|
139
144
|
对每个 `Display=1` 或 `AppDisplay=1` 且绑定业务表的 Diy 模块,AI 不能只依赖 CRUD
|
|
140
145
|
默认页,也不能只写 `Name/DiyTableId` 后结束。至少完成以下设计和回读:
|
|
141
146
|
|
|
@@ -298,6 +303,9 @@ PageTabs 通过 `TargetSysMenuId` 切换不同模块/表时,入口模块必须
|
|
|
298
303
|
- PC 和移动端分别验证;MicroService 还要验证运行时、页面路由和宿主上下文。
|
|
299
304
|
### 多级表头与顶部 Banner
|
|
300
305
|
|
|
306
|
+
- UniApp 通用模块行按钮使用 `MoreBtns[].ActionSchema` 进入列表“更多”;详情合并 `FormBtns`、`MoreBtns` 与视图 `Layout.Actions`,按 `Key` 去重,常用动作与编辑并排放到底部固定栏,其余进入“更多”。仅 PC `V8CodeShow` 不构成移动端显隐条件,必须另给 `VisibleWhen`;接口继续鉴权。该渲染行为需重新编译 UniApp 客户端,不能把菜单保存当作客户端已更新。
|
|
307
|
+
- `Layout.Hero` 辅助文字使用 `MetaField`,不使用未支持的 `SubtitleField`;图片、背景、设备/客户字段由模块元数据提供,禁止写死到通用页面。无业务图标的统计卡只居中展示条数,不显示平台占位图标。
|
|
308
|
+
|
|
301
309
|
- 字段权限使用模块 `FieldPermissions`(Manifest `fieldPermissions`),Version=1;按 Everyone/Roles/Users/Departments/Jobs 与 Fields 配置 Visible/Editable,授权对象数组保存 Id。多个匹配组限制取交集,隐藏同时不可编辑;普通用户按最终能力执行,超级管理员按原管理边界。岗位来自 `diy_job`(显示 `JobName`),匹配权威 `sys_user.Jobs` 中的岗位 Id;岗位与角色 `RoleIds` 分开,不得相互替代。
|
|
302
310
|
- 不能只做前端隐藏:FormEngine 查询、隐藏字段条件/排序/统计、导出、写入和导入均须校验。生成代码使用服务端 `DataAppend.FieldAccess`;未传菜单的客户端不能绕过该表已启用的模块限制。验收应覆盖普通账号、直接请求、角色/人员/部门/岗位匹配与只读写入失败。
|
|
303
311
|
- 树模块拖动排序配置 `TreeDragSortEnabled`、`TreeDragSortField`(Manifest 同名小驼峰),排序字段必须为已注册数值字段。业务由 Managed、非匿名接口引擎 `mci-tree-drag-sort` 执行,可信原子仅负责固定引擎的模块解析、权限和白名单写入。
|
|
@@ -38,6 +38,19 @@ for (const name of names) {
|
|
|
38
38
|
text += `\n\n${fs.readFileSync(source, 'utf8')}`;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
+
// 常规责任 Skill 也会把必读决策和源码索引放到 references;平台 AI 无法访问工作区路径,
|
|
42
|
+
// 必须把显式链接的同目录参考一并嵌入,不能只同步一张指向不可读文件的入口。
|
|
43
|
+
const included = new Set(references.map(reference => reference.path));
|
|
44
|
+
const entry = fs.readFileSync(path.join(skillsRoot, name, 'SKILL.md'), 'utf8');
|
|
45
|
+
const localReferences = [...new Set([...entry.matchAll(/(?:\(|`)(references\/[^\s)`#]+\.md)(?:#[^\s)`]*)?(?:\)|`)/g)].map(match => match[1]))].sort();
|
|
46
|
+
for (const reference of localReferences) {
|
|
47
|
+
if (included.has(reference)) continue;
|
|
48
|
+
const source = path.resolve(skillsRoot, name, reference);
|
|
49
|
+
const relative = path.relative(path.join(skillsRoot, name), source);
|
|
50
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) throw new Error('参考文件越过 Skill 目录。');
|
|
51
|
+
text += `\n\n${fs.readFileSync(source, 'utf8')}`;
|
|
52
|
+
included.add(reference);
|
|
53
|
+
}
|
|
41
54
|
text = `${stripMarkers(text).replace(/\r\n/g, '\n').trimEnd()}\n`;
|
|
42
55
|
const target = path.join(serverRoot, 'Resource', file);
|
|
43
56
|
const before = fs.existsSync(target) ? fs.readFileSync(target, 'utf8') : '';
|
|
@@ -36,6 +36,9 @@ Microi 上传字段存在四种必须长期兼容的存储形态,不能假设
|
|
|
36
36
|
|
|
37
37
|
`FileServer` 是对象存储/CDN 地址,不等同于 API 服务。租户切换时必须使用当前 `OsClient` 的运行期配置,禁止在源码中写死域名或租户目录。
|
|
38
38
|
|
|
39
|
+
- 历史配置的原始 `FileServer` 主地址兼容 HTTP/HTTPS。公有相对路径的兼容回退保留协议、端口和路径前缀,不强制升级 HTTPS,也不改拼 API Base;仅此原始主地址允许 HTTP。备用绑定、源地址映射和别名仍限定 HTTPS 并通过原验证,私有路径、带凭据地址及危险协议的限制不变。
|
|
40
|
+
- 公共解析器以 `Microi.Client/src/utils/public-resource-router.mjs` 为单一事实源;修改后运行 `node microi.skills/scripts/sync-public-resource-router.mjs --write` 同步三份 SDK 生成块并执行 `--check`。PlatformService 的 SDK 属于其源码输入,变更后必须按原生 Bundle 入口重建及更新四个所属应用包,不能只更新 PC 或手改嵌入 Base64。
|
|
41
|
+
|
|
39
42
|
### 跨端上传字段的形态与桶属性
|
|
40
43
|
|
|
41
44
|
- 控件读取嵌套 `Config.ImgUpload/FileUpload.Multiple` 与 `MaxCount`;`Multiple=false` 保存单图对象,不能因数量上限或默认九图值而保存数组。已有单元素数组在单图控件中按第一项读取,不在查看时回写业务数据。
|
|
@@ -25,24 +25,25 @@ description: Microi V8 与 MCP 文件上传下载指南。用于流式发布、
|
|
|
25
25
|
|
|
26
26
|
文件与发布测试默认使用当前 MCP 连接下、当前租户实际生效的 HDFS Provider;先只读核实提供商与对象范围,沿已授权隔离前缀执行公私权限、原始字节、哈希、MIME 与写后回读断言。已确定当前环境后,不再为其它 OSS/MinIO/S3 反复询问或新建存储;仅明确的提供商缺陷、迁移或兼容任务才扩展矩阵,并逐项报告真实执行与未覆盖范围。提供商不可用或断言失败必须保留真实错误,不能换提供商或省略回读来冒充通过。
|
|
27
27
|
|
|
28
|
-
公开入口覆盖 `V8.uploadFile`、多文件 `V8.uploadFiles` 与 MCP `microi_upload_file_base64`。多文件上传必须限制并发、逐文件返回结果;Base64
|
|
28
|
+
公开入口覆盖 `V8.uploadFile`、多文件 `V8.uploadFiles` 与 MCP `microi_upload_file_base64`。多文件上传必须限制并发、逐文件返回结果;Base64 工具只接受明确文件名、大小和租户内目标范围,写后回读路径、大小与哈希。遇到 `OBJECT_STORAGE_CONFIG_INCOMPLETE` 先按[OSS 配置诊断](references/progressive-01-公有桶-vs-私有桶.md#oss-配置不完整的诊断)核对实际 HDFS 和所需桶,不直接要求购买阿里云。
|
|
29
29
|
|
|
30
30
|
公开运行资源的备用地址只通过 `V8.Method.GetPublicResourceBackupUrl({FilePathName:'tenant/micro-app/app/index.html'})` 只读选择,返回 `{Code:1,Data:{UseBackup,Url}}`。只允许 `FilePathName`,不能传 URL、Ready、SHA、流量、凭据或用户身份;当前公开应用、完整版本清单、签名副本与 NAS 健康必须同时匹配。`UseBackup=false`、异常或旧后端缺少该能力时继续原公开地址,不把 `FileServerBak` 非空或目录存在当作可用副本;该方法不复制对象、不读取私有文件,也不授予管理权限。管理和迁移仍走已有受信任应用接口,并分别回读副本完整性与真实消费结果。
|
|
31
31
|
|
|
32
|
+
专用公开导入桶与 `V8.Method.GetCompletedPublicUploadProof` 的配置、授权、提升和失败边界,完整读取[专用公开导入协议](references/hotspot-offload-operations.md#专用公开导入桶与可信媒体证明)。
|
|
32
33
|
## MCP stdio 与完整包的传输边界
|
|
33
34
|
|
|
34
35
|
### 普通本机文件上传与备用公私目标
|
|
35
36
|
|
|
36
37
|
- 先回读 `microi_get_status.PrivateFileUploadProtocol` 或 `microi_manage_file_stream_upload action=Capabilities`;支持值为 `PrivateFileUpload/1`。工具已安装不等于 API 已升级,旧 API 不支持时失败关闭,不能改走公有应用发布。
|
|
37
38
|
- `microi_upload_file_stream.localFilePath` 是 MCP 客户端电脑上的普通文件,由客户端读取原始字节、固定 16 MiB 分片;32 GiB 只是协议硬上限,实际仍受 SaaS FileUploadMaxFileMB/MaxRequestMB、DisableFileUpload 与共享日用户/租户额度约束。首次写入分片走现有 UploadQuota 原子额度,确认分片重放不重复预留,失败不退款。不要与旧 `microi_import_external_attachment.sourcePath` 混淆:后者是 API 服务账号能访问的服务器绝对路径/UNC,目标仍是主 HDFS。
|
|
38
|
-
- `target` 默认 `Primary`,`Primary` / `BackupPrivate` 均为私有;显式 `BackupPublic` 只把最终文件写入当前租户 SaaS MinIO 公桶。两种备用目标都核对 `FileServerBak` 公网绑定,暂存私桶不同于公桶且只读策略检查通过;不切换 HDFS、不允许自由 Endpoint/Bucket
|
|
39
|
+
- `target` 默认 `Primary`,`Primary` / `BackupPrivate` 均为私有;显式 `BackupPublic` 只把最终文件写入当前租户 SaaS MinIO 公桶。两种备用目标都核对 `FileServerBak` 公网绑定,暂存私桶不同于公桶且只读策略检查通过;不切换 HDFS、不允许自由 Endpoint/Bucket/凭据。未配置专用公开导入桶时,公开授权只对签名 Completed 的单个最终对象追加匿名 GetObject,保留其它 Statement,不开放整桶、前缀、ListBucket/PutObject 或私桶;专用桶例外仅限下述独立受保护命名空间。只接受交互式平台管理员,禁止访问密钥会话。
|
|
39
40
|
- 只有用户明确授权选定文件可由所有人访问时才使用 `BackupPublic`,必须 `publishPublic=true`、`confirmExecution="PUBLIC:" + requestId`;私有目标确认仍是原 requestId。没有公开意图的旧调用保持私有;图库/人脸/其它私密资料不随示例公开。公开会话分片、签名清单和回执始终私有,目标和公开意图绑定签名,不能把既有私有会话换目标公开。
|
|
40
41
|
- 该入口对 MinIO 检查桶策略、OSS 检查私有 ACL 与桶策略;S3 尚缺完整私有 ACL 证明,`StorageProviderSupported=false` 时不上传。Capabilities 仅展示协议/配置,不代替实际桶权限验证。32 GiB 协议格式不放宽普通上传绝对 2 GiB 单文件/总请求保护。
|
|
41
42
|
- 稳定 `requestId` 固定原始 SHA-256/大小/每片哈希、操作者、租户及存储绑定;不确定结果先 Status 后同键续传。MCP 本机检查点不含凭据;跨客户端带原回执 `expectedStorageBindingHash`。不能取新 binding 伪装旧会话恢复。
|
|
42
43
|
- 最终返回 Completed 前服务端合并并回读原始字节 SHA-256;独立验收调用 Verify,不拿 ETag、200、元数据或上传结束代替原片完整性。会话清单/块/回执始终私有并 HMAC 绑定精确对象键,底层使用既有 HDFS 流、原生鉴权和 renewable lease,不经过 V8 大对象。
|
|
43
44
|
- 未完成会话有效期 7 天,Abort 只清理拥有的 staging;完成自动清理失败显示 CleanupComplete=false,重复 Complete/Abort 可补清。不得删除用户最终原片。签名清单/终态回执保留审计;暂存磁盘有界内存流式,最终合并需要与原片等量的临时空间。
|
|
44
45
|
- BackupPrivate 回执的 FilePathName 不能当主 HDFS 路径交给旧 GetPrivateFileUrl。没有备用私有下载票据能力时仅交付后端 Verify 证据,不能拼匿名 URL 或改公桶。当前公开热点分流仍只处理公开资源,与本协议隔离。
|
|
45
|
-
- `BackupPublic` 自动公开要求后端 8.8.6 与支持该动作的 MCP,Capabilities 必须回读 `PublicObjectPublicationProtocol=ExplicitPublicObjectRead/1`;8.8.5
|
|
46
|
+
- `BackupPublic` 自动公开要求后端 8.8.6 与支持该动作的 MCP,Capabilities 必须回读 `PublicObjectPublicationProtocol=ExplicitPublicObjectRead/1`;8.8.5 只完成存储,不能补新对象匿名授权。未配置专用桶时,客户端完成后执行写动作 `PublishPublic`:签名 Completed + 全量 SHA 校验在前,与热点分流共享同一桶策略租约,精确追加该对象 GetObject 后重新校验管理员、绑定及全量 SHA,再匿名 HEAD/首段 Range,成功才返回 PublicUrl。原 Statement 保持;同名 Sid 异常/条件/策略变量/通配符拒绝,不静默修复。写入结果未知保留 MayHaveAddedGrant 事实,失败以新租约只撤本次可能新增授权,回报 PublicPolicyRollbackConfirmed;不能撤此前已核实的既有授权。共享租约+写前比较仅协调平台写入者,不宣称 SDK 对外部管理员有原子 If-Match。
|
|
46
47
|
- `ProbePublic` 始终只读,仍执行全量存储 Verify + 可信 FileServerBak 匿名校验;匿名范围最多16MiB,不冒称全文件已匿名下载。无 Cookie/凭据/重定向,大文件错误200只读头拒绝,不下载全片。独立 Complete 仅完成存储;失败 Code0 保留 Completed/字节证据,原 requestId 可恢复,或显式 `PublishPublic` 携带原 sessionId/binding、BackupPublic、publishPublic=true 与 `confirmExecution="PUBLIC:"+sessionId` 重新授权,不换请求号重复上传。已 Completed 会话可超过7天恢复,未完成会话寿命不变。管理 Complete 的公开确认也是 `PUBLIC:` + sessionId,Abort 仍原 sessionId且只清理自有暂存。
|
|
47
48
|
|
|
48
49
|
- 标准 MCP 服务的 stdio 使用固定 `128 MiB`(`134217728` 字节)未解析 JSON-RPC 缓冲,超过边界立即拒绝并关闭连接;不读取动态环境变量放大。SDK 调用端若仍使用默认 `10 MiB` 缓冲,大响应仍可能关闭客户端,必须核对调用端支持的真实边界。
|
|
@@ -52,6 +53,9 @@ description: Microi V8 与 MCP 文件上传下载指南。用于流式发布、
|
|
|
52
53
|
小型指针/回执,不把私有源码、超大资产常态化塞入 JSON/Jint;支持更大正文的其它
|
|
53
54
|
连接也须有明确边界。不能用增大stdio缓冲绕过能力鉴权、业务配额或包完整性检查。
|
|
54
55
|
|
|
56
|
+
`ProbePublic` 的可选 `PublicPolicyDiagnostics` 仅输出固定 `FailureStage/ReasonCode/SdkCode`、有界字节数/语句数及真实布尔状态;合法字段名中的任意 URL、异常文本、策略正文、资源 ARN 和秘密仍被拒绝,未知保留 `Unknown`,不从错误文本推断 Redis 故障。原当前管理员、签名会话 owner/tenant/binding/Completed 和完整 SHA 验证保持,之后仅 GetPolicy + 纯规则检查,不调用 Set/Remove。
|
|
57
|
+
旧适配器缺诊断能力返回 `UnsupportedDiagnostics`,仍继续原独立匿名 HEAD/Range;策略失败不覆盖匿名结果,策略就绪不等于公开可读。`PublishPublic` 沿用同样白名单诊断,保持未知 SET 后回读、共享租约和仅撤销本次新增授权的规则;诊断观察器不能改变写入顺序。
|
|
58
|
+
|
|
55
59
|
## 表单字段的公有桶与私有桶(强制)
|
|
56
60
|
|
|
57
61
|
- `Config.FileUpload.EnableRolePermission=true` 的字段强制私有上传,优先级高于字段和请求 `Limit`。
|
|
@@ -116,3 +116,21 @@ ObjectKeys 协议最多 100 项,不代表一轮可确认任意数量的独立
|
|
|
116
116
|
- 历史 archive 状态独立主库签名/CAS,人工选择不伪造当前流量;重复 Pin 保留停用。8 MiB 原生分块、NAS multipart 与逐段匿名校验都保存可恢复回执,完整权威 SHA 才 Ready;源/目标变化先撤旧公开授权,私有暂存所有权保留待清理。匿名 Managed HTTP mci-file-resource-archive-download 只读重验后 302 到已验 NAS 或同一历史版本原云地址;私有/权威缺失拒绝。先部署接口再发官网,按 more/hdfs.md 分层验收。
|
|
117
117
|
- 七文件消费者为 public-resource-router.mjs、diy.common.js、diy-imgupload.vue、diy-fileupload.vue、DiyTableSpecialCell.vue、diy-common.mixin.js、diy-richtext.vue:显式 Limit:false 初始 src/链接/新富文本插入前 await 批量原生 GenericPublicResourceRoutes/1,校验绑定、源/行/字段/租户身份,可观测错误最多一次原址回退。卡片 helper 无活动调用点不能算额外页面覆盖;私有、旧富文本 HTML、Three.js/AI 硬编码 URL、平台 bootstrap、独立 JS 缺清单、ZIP 聚合/下游 Office 仍未覆盖;完整入口和 HEAD 后失败限制见官网 more/hdfs.md。
|
|
118
118
|
<!-- /microi-progressive:chunk -->
|
|
119
|
+
|
|
120
|
+
## 专用公开导入桶与可信媒体证明
|
|
121
|
+
|
|
122
|
+
- 后端 8.8.8 的 SaaS `MinIOExplicitPublicBucketName` 为非敏感用途桶名,默认空保持旧协议;不复制/继承主租户,不改变 `MinIOPublicBucketName`。工具仍使用原 `BackupPublic + publishPublic + PUBLIC:原请求/会话`,不增加用户自由桶/URL/凭据参数。图库和人脸资料不因示例公开而公开。
|
|
123
|
+
- 仅接管本协议在当前目标绑定下创建并有私有 HMAC 回执的桶。未知已有桶即使空也拒绝。只对专用桶当前租户 `public/v1/{tenant}/` 设置 GetObject,不改旧桶策略或私桶,不授权 List/Put;普通 HDFS 上传/复制/移动/删除不可进入用途桶与保留私有提升目录。
|
|
124
|
+
- 完整源 SHA → ETag/版本条件 COPY 到私有保护暂存 → 暂存完整 SHA → 条件提升 → 目标完整 SHA → 无凭据匿名 HEAD/最多16MiB Range → 私有公开证明。旧来源绑定不变,目标 `PublicStorageBindingHash` 单独派生。COPY 结果未知只读恢复,同内容复用、冲突拒绝;MinIO7需用 CopyConditions.SetMatchETag,不能只用会被内部丢弃的 WithMatchETag;需转义的 VersionId 失败关闭,不降级无版本复制。
|
|
125
|
+
- 创建前失败且桶仍不存在可续原意图;创建响应未知而桶已存在返回 BucketCreationNeedsReconciliation,不猜归属接管。专用 ProbePublic 只有读取,不建桶/复制/写策略/补回执。PromotionStageCleanupComplete=false 可原 PublishPublic 重试补清自有私有暂存;不能删除来源、公开最终对象或其它会话。
|
|
126
|
+
- `V8.Method.GetCompletedPublicUploadProof({SessionId})` 仅固定 Managed `platform-vision-media`、当前管理员/tenant/owner;依赖可选后端 provider,缺失拒绝。签名原清单、源/目标全SHA、已持久匿名证明和当前匿名回读均通过才返回 ObjectId、Completed、Bytes、Sha256、PublicUrl、目标 StorageBindingHash、SourceStorageBindingHash、BlockBytes=16777216 和 BlockHashes。业务 V8 不接受前端自报块摘要或 URL 冒充受信对象。
|
|
127
|
+
- MinIO20KiB策略上限不提高;容量失败也保留有界语句/资源/重复计数,不回传策略/ARN。旧热点组没有明确过期归属证据时不得删除或撤权。本地夹具、编译和镜像发布不代替 NAS 实际 COPY、完整字节和匿名访问交付。
|
|
128
|
+
|
|
129
|
+
### 大文件持久操作协议
|
|
130
|
+
|
|
131
|
+
- 后端 8.8.9 与支持该能力的 MCP 使用 `PrivateFileOperation/1`。必须回读实际 Capabilities 的 `AsyncOperationsProtocol=PrivateFileOperation/1`、`AsyncOperations` 及当前 `OwnerId`;`Complete/Verify/PublishPublic/ProbePublic` 通过 `QueueOperation/GetOperation/CancelOperation` 复用已有持久任务,固定 16 MiB Part 与原完整 SHA、配额、公开授权和源/目标绑定不变。HTTP 提交与查询保持短请求,完整处理保留原长操作预算;不能全局拉长超时、替换 ApiBase、绕过网关或跳过校验。
|
|
132
|
+
- 排队/执行中 `Code=2` 不是成功。请求固定绑定当前 tenant、交互式管理员 owner、原会话、来源与目标配置、operation 和 requestId;持久任务不保存原 DiyToken、自由 URL 或存储凭据。执行及读取重验当前管理员与配置,后台固定 native worker 不交给可编辑 V8。复用现有租约、fence 和可恢复存储原子,不能使用请求后的 Task.Run。
|
|
133
|
+
- MCP 独立保存不含秘密的操作检查点。提交响应未知先按同一 requestId 查询,不能生成新号绕过未知状态;结果失败、取消或绑定不一致时失败关闭。`Status` 只读会话不等于 Verify/Probe;终态成功仍逐项校验原始字节、SHA、owner、session、目标及匿名证明。取消是请求,不承诺存储 SDK 即刻终止。
|
|
134
|
+
- `CompletedPublicProof` 只能由固定受管 `platform-vision-media` 的可信原子入队;公开 `QueueOperation` 拒绝该操作。MCP `GetOperation` 可用同一 owner 的 Target/SessionId/StorageBindingHash 精确定位证明任务,仅回进度和过期标记,不返回证明正文或触发写入。新证明成功后在当前绑定下最多复用 5 分钟,过期通过限定 CAS 刷新同一任务、推进 fence,不重复创建活动任务;业务不能把旧签名内容当作无限期授权。
|
|
135
|
+
- 失败的内部证明不得无限期缓存为不可恢复状态。保留旧失败状态、时间与 fence 日志,至少冷却 15 秒后,受管原子才可 CAS 恢复同一证明 TaskId 并重新执行只读验真;读取进度不触发恢复,Cancelled 不自动重启,公开发布动作不借用此机制重复写入。客户端发现失败先保存回执,不能直接当 Pending 继续循环。
|
|
136
|
+
- 首次受管证明返回 Pending 时保留原媒体登记参数;先读精确证明任务进度,再重试原登记并独立 Describe 回读。若业务接口把 Pending 转为失败文本,不能把它判成已登记,也不能改用客户端自报 URL/块哈希。证明任务必须独立于外层 V8 的 Code0 回滚持久化,验收覆盖该场景、重启续作、未知提交、撤权与绑定变化。
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
> 按需读取;本文件由 SKILL.md 的原章节无损拆分。
|
|
4
4
|
|
|
5
|
-
<!-- microi-progressive:chunk id=v8-file-upload-005 sha256=
|
|
5
|
+
<!-- microi-progressive:chunk id=v8-file-upload-005 sha256=4922ff1364f2a9994d7cc47ff224e07c794e382b6f5f44b75b76ae365f7efff1 -->
|
|
6
6
|
## 公有桶 vs 私有桶
|
|
7
7
|
|
|
8
|
+
### OSS 配置不完整的诊断
|
|
9
|
+
|
|
10
|
+
- `OBJECT_STORAGE_CONFIG_INCOMPLETE` 不等于必须购买阿里云。先核对当前生效租户三参数和 SaaS `HDFS`(`Aliyun/MinIO/S3`);旧库未设置时兼容默认 Aliyun。实际使用其它提供商时,通过既有 SaaS 配置入口修正并刷新缓存,不自动切换存储或借用主租户密钥。
|
|
11
|
+
- 含按桶校验修复的 OSS `PutObject` 仅校验并初始化本次所需桶:普通 `Limit=false/null` 检查 `AliOssPublic*` 四项,`Limit=true` 检查 `AliOssPrivate*` 四项;每组为 `BucketName/Endpoint/AccessKeyId/AccessKeySecret`。只有 `Preview=true` 且有 `FileFullPathOrigin` 时额外读取私有原图;生成公有预览需两组。缺项失败关闭,错误保留 `ErrorType`、`StorageScope` 和字段名,不输出配置值。
|
|
12
|
+
- 旧后端可能把公私两套配置一并报缺。此修复不能生成有效密钥;完整微服务交付包含私有源码和公有编译产物,仍须配置相应两类存储并验证 FileServer/CDN。只完成单桶上传不等于完整发布、回滚或客户验收成功。现有 MCP 发布/上传入口可继续复用,无需改工具签名。
|
|
13
|
+
|
|
8
14
|
### 应用商城 ZIP
|
|
9
15
|
|
|
10
16
|
应用商城的 AI 应用/微服务资产禁止逐文件 Base64 持久化到数据库。源码/安装包场景可以生成 ZIP;真实在线编译目录优先使用下节的 MCP 流式发布。数据库只保存路径和校验元数据。
|
|
@@ -25,11 +25,16 @@ description: Microi 前端 V8 事件与客户端能力指南。用于编写浏
|
|
|
25
25
|
- 登录后的敏感操作使用 `V8.Identity.Verify` 完成 Passkey/严格人脸交互;前端只取得一次性 Ticket,后端接口引擎必须重算 `ActionHash` 并原子消费,不能把前端成功当作授权。
|
|
26
26
|
|
|
27
27
|
<!-- /microi-progressive:chunk -->
|
|
28
|
-
<!-- microi-progressive:chunk id=v8-frontend-events-001 sha256=
|
|
28
|
+
<!-- microi-progressive:chunk id=v8-frontend-events-001 sha256=bf7d6288bece731f78dbfa29b0e04ff56631d3693979bb91d759fe26ef92d0ec -->
|
|
29
29
|
## 字段事件(在【字段属性】中配置)
|
|
30
30
|
|
|
31
31
|
### FieldValueChange — 值变更事件(最常用)
|
|
32
32
|
|
|
33
|
+
关联回填先读 `../microi-form-engine/references/form-generation-quality.md`。`ThisValue`
|
|
34
|
+
不是固定行对象:保存格式为 Text 时可能是原始键,Department 可能是路径,多选是数组。
|
|
35
|
+
先按来源保存键解析,再逐字段回填;处理清空、改选、失败和异步代次,不从名称猜来源列。
|
|
36
|
+
只有已确认选择是行对象且保存键确为 Id 时才能读取 `V8.ThisValue.Id`,不能用于原始键或部门路径。
|
|
37
|
+
|
|
33
38
|
```javascript
|
|
34
39
|
// V8.EventName === 'FieldValueChange'
|
|
35
40
|
// V8.ThisValue — 当前字段新值
|
|
@@ -42,8 +47,11 @@ description: Microi 前端 V8 事件与客户端能力指南。用于编写浏
|
|
|
42
47
|
if (V8.LoadMode === 'Design') return;
|
|
43
48
|
|
|
44
49
|
// 选择部门 → 联动加载该部门下的人员到 联系人 控件
|
|
45
|
-
var
|
|
46
|
-
if (
|
|
50
|
+
var selection = V8.ThisValue;
|
|
51
|
+
if (Array.isArray(selection)) selection = selection.length ? selection[selection.length - 1] : '';
|
|
52
|
+
var deptId = selection && typeof selection === 'object' ? selection.Id : selection;
|
|
53
|
+
V8.FormSet('Contact', ''); // 清除原部门的联系人,不能只更换候选列表
|
|
54
|
+
if (deptId !== '' && deptId !== null && deptId !== undefined) {
|
|
47
55
|
var users = await V8.FormEngine.GetTableData('Diy_Employee', {
|
|
48
56
|
_SelectFields: ['Id', 'Name', 'Account'],
|
|
49
57
|
_Where: [['DeptId', '=', deptId]]
|
|
@@ -53,14 +61,14 @@ if (deptId) {
|
|
|
53
61
|
V8.FieldSet('Contact', 'Data', []);
|
|
54
62
|
}
|
|
55
63
|
|
|
56
|
-
//
|
|
57
|
-
|
|
64
|
+
// 对其它业务字段的回填需先取得并校验授权来源记录。
|
|
65
|
+
// 不要无条件用 V8.ThisValue.Name;Text 保存格式可能只有 Id。
|
|
58
66
|
|
|
59
67
|
// 联动显隐
|
|
60
68
|
V8.FieldSet('TaxNo', 'Visible', V8.ThisValue === '企业');
|
|
61
69
|
|
|
62
70
|
// 联动必填
|
|
63
|
-
V8.FieldSet('Reason', '
|
|
71
|
+
V8.FieldSet('Reason', 'NotEmpty', V8.ThisValue === '退款');
|
|
64
72
|
```
|
|
65
73
|
|
|
66
74
|
### FieldOnKeyup — 键盘抬起事件
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: v8-image-processing
|
|
3
|
-
description: Microi V8.Image
|
|
3
|
+
description: Microi V8.Image 服务端图像处理指南。用于图片生成、合并、水印、缩放、裁剪、格式转换、文字绘制、二维码与元数据读取,以及多页中文 PDF 的字体缓存释放、原生内存增长排查和安全 Base64/Data URI 流程。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
> **Microi吾码基础规范(强制):** 任何 AI 模型与宿主每次新建或接续吾码任务,先完整读取 `../workspace-conventions/SKILL.md`,必须执行版本播报、`@microi.net/cli` 后台自动升级、Skills/MCP 同步和进度播报。安装与诊断读取 `../microi-codex-installer/SKILL.md`;更新失败延后重试,不阻断当前工作。
|
|
7
7
|
|
|
8
8
|
# Microi V8 图像处理
|
|
9
9
|
|
|
10
|
-
使用 `V8.Image`
|
|
10
|
+
使用 `V8.Image` 在服务端处理内存图片。图像操作接收对象参数并返回 `DosResult`;图片结果位于 `result.Data.FileByteBase64`。`ReleaseFontCache()` 是无参维护方法,仅返回缓存统计。
|
|
11
11
|
|
|
12
12
|
## 核心原则
|
|
13
13
|
|
|
@@ -52,6 +52,7 @@ var source = {
|
|
|
52
52
|
| 添加常规图片水印 | `V8.Image.Watermark` | `BaseImage`、`Watermark`、`Position`、`Opacity` |
|
|
53
53
|
| 生成二维码 | `V8.Image.CreateQRCode` | `Content`、`Size` |
|
|
54
54
|
| 读取宽高、格式等元数据 | `V8.Image.GetInfo` | 任一图片来源字段 |
|
|
55
|
+
| 批量文字绘制后释放字体缓存 | `V8.Image.ReleaseFontCache()` | 无参数;返回缓存字节统计,不返回图片 |
|
|
55
56
|
|
|
56
57
|
### 3. 设计合并布局
|
|
57
58
|
|
|
@@ -169,8 +170,18 @@ return result;
|
|
|
169
170
|
- 通用规则:图片文字能力必须随 `Dos.Common` 程序集嵌入许可允许再分发的中英文字体;解析顺序固定为指定/系统字体、内置字体、明确缺字错误,禁止把“请运维安装字体”作为基础文字功能的唯一方案。
|
|
170
171
|
- 自动化检查:除 Windows 单元测试外,必须在 `FONTCONFIG_FILE` 指向空字体目录的 Linux 容器中验证英文、数字、中文和不存在的 `FontFamily`,同时确认系统 `MatchCharacter` 返回空、输出存在有效文字像素且没有缺字方框。
|
|
171
172
|
|
|
173
|
+
## 多页中文绘制与字体缓存
|
|
174
|
+
|
|
175
|
+
- 先区分照片像素内存、托管堆和原生字体缓存。缩放照片不能解决字体实例累积;案例册和报表若都调用 `Create`/`Draw` 绘制中文,就共享同一字体处理路径。
|
|
176
|
+
- 使用后端 `V8.Image.ReleaseFontCache()` 在页或批次边界清理,通常放在绘制前和 `finally` 中。普通单图无需机械添加,不得逐字符调用或把它放进匿名的独立“清缓存”接口。
|
|
177
|
+
- 最小调用:`var released = V8.Image.ReleaseFontCache(); if (!released || Number(released.Code) !== 1) return released || { Code: 0, Msg: '字体缓存释放未返回结果' };`。完整绘制与失败路径示例见 [API 参考](references/api-reference.md#releasefontcache-释放字体缓存)。
|
|
178
|
+
- `BeforeBytes/AfterBytes` 是进程共享字体缓存统计;并发时缓存会重建,不能断言清零、单调下降或将差值当作 RSS 释放量。调用不强制 GC、不改限额、不清 Redis。
|
|
179
|
+
- 先确认实际 API 进程已加载包含该方法的 `Microi.V8Engine`。旧部署可明确失败,或按业务要求兼容继续并标记能力未启用;不得吞掉错误后宣称问题已修复。更新 Skills、接口代码或编译成功都不能替代程序集部署和重启。
|
|
180
|
+
|
|
172
181
|
## 验收清单
|
|
173
182
|
|
|
183
|
+
- 多页中文 PDF/图片出现 RSS 快速上升时,区分托管累计分配、托管存活堆和原生字体缓存。`V8.Image.ReleaseFontCache()` 是无参原子能力,返回 `{Code:1,Data:{BeforeBytes,AfterBytes}}`,可在每页绘制前后调用;不修改缓存限额、不强制 GC,影响进程共享字体缓存。缓存字节不是 RSS 释放量。先确认部署包含该方法,旧服务器兼容跳过必须在诊断结果中明确标记;不能仅靠文件缓存命中、重试或本地编译宣称内存问题已解决。
|
|
184
|
+
|
|
174
185
|
- 确认每个图片来源都来自受信任的内存数据,并且没有把路径或 URL 直接传给 `V8.Image`。
|
|
175
186
|
- 确认处理链中每一步都检查 `Code === 1`。
|
|
176
187
|
- 确认覆盖图层的 `ZIndex`、`X/Y` 或 `Position` 与预期一致。
|
|
@@ -19,12 +19,13 @@
|
|
|
19
19
|
15. [GetInfo 读取信息](#getinfo-读取信息)
|
|
20
20
|
16. [兼容别名](#兼容别名)
|
|
21
21
|
17. [颜色、格式与资源限制](#颜色格式与资源限制)
|
|
22
|
+
18. [ReleaseFontCache 释放字体缓存](#releasefontcache-释放字体缓存)
|
|
22
23
|
|
|
23
24
|
## 调用与返回约定
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
除无参 `ReleaseFontCache()` 外,公开方法接收一个参数对象。底层也兼容内容为 JSON 对象的字符串,但 V8 代码应优先直接传对象,并使用规范的 PascalCase 字段名。
|
|
26
27
|
|
|
27
|
-
处理成功时,除 `GetInfo` 外均返回:
|
|
28
|
+
处理成功时,除 `GetInfo` 和 `ReleaseFontCache` 外均返回:
|
|
28
29
|
|
|
29
30
|
```javascript
|
|
30
31
|
{
|
|
@@ -42,6 +43,8 @@
|
|
|
42
43
|
}
|
|
43
44
|
```
|
|
44
45
|
|
|
46
|
+
`V8.Image.ReleaseFontCache()` 返回 `{Code:1,Data:{BeforeBytes,AfterBytes}}`。这是进程共享字体缓存统计,不是 RSS 释放量;调用只释放可回收字体缓存,不修改限额或强制 GC。多页绘制可在页面前及 `finally` 中调用,正常绘制会重新建立需要的缓存;不得每个字符清理。旧服务器需升级 `Microi.V8Engine`,兼容跳过不能记录为成功。
|
|
47
|
+
|
|
45
48
|
处理失败时返回 `Code: 0`,错误说明位于 `Msg`。任何调用链都必须先判断 `Code`:
|
|
46
49
|
|
|
47
50
|
```javascript
|
|
@@ -98,7 +101,7 @@ var result = V8.Image.GetInfo({ Bytes: response.RawBytes });
|
|
|
98
101
|
|
|
99
102
|
## 公共输出参数
|
|
100
103
|
|
|
101
|
-
除 `GetInfo` 外,各方法均支持以下参数:
|
|
104
|
+
除 `GetInfo` 和无参 `ReleaseFontCache` 外,各方法均支持以下参数:
|
|
102
105
|
|
|
103
106
|
| 参数 | 默认值 | 说明 |
|
|
104
107
|
|------|--------|------|
|
|
@@ -127,9 +130,52 @@ var result = V8.Image.GetInfo({ Bytes: response.RawBytes });
|
|
|
127
130
|
| `V8.Image.Watermark(param)` | 按锚点添加图片水印 |
|
|
128
131
|
| `V8.Image.CreateQRCode(param)` | 生成二维码 |
|
|
129
132
|
| `V8.Image.GetInfo(param)` | 读取图片元数据,不重新编码 |
|
|
133
|
+
| `V8.Image.ReleaseFontCache()` | 无参;释放本进程可回收字体缓存,返回统计,不返回图片 |
|
|
130
134
|
|
|
131
135
|
`RemoveSolidBackground` 参数:内存图片来源、`Tolerance`(默认 36)、`Feather`(默认 24)、可选 `ChromaKeyColor`(如 `#00ff00`)、`EdgeConnectedOnly`(默认 false)、`SuppressGreenSpill`(默认 false)。开启边缘连通限制可保护主体内部同色区域;封闭背景孔洞可能保留,需检查输出。专门生成的纯绿幕素材可指定绿色并开启去溢绿,清除封闭绿幕孔洞及边缘混色;主体本身为绿色时不得开启。未指定抠像色时估计四角背景色。输出固定 PNG,输入上限为 20,000,000 像素,不接受任意图片 URL。
|
|
132
136
|
|
|
137
|
+
## ReleaseFontCache 释放字体缓存
|
|
138
|
+
|
|
139
|
+
签名:`V8.Image.ReleaseFontCache()`,仅后端可用,无参数。成功返回:
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
{ Code: 1, Data: { BeforeBytes: 20480, AfterBytes: 0 } }
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
以上数字仅作字段示例,不能作为预期值。失败返回 `Code:0` 和 `Msg`;方法不存在的旧程序集可能直接抛错,必须显式处理。
|
|
146
|
+
清理作用于当前进程共享的 Skia 字体缓存,不区分租户、不跨节点、不修改缓存上限或执行 GC。
|
|
147
|
+
活跃绘制仍可持有字体,并发可重新填充缓存,所以 `AfterBytes` 不保证为零,也不保证小于 `BeforeBytes`。
|
|
148
|
+
它不会清 Redis、释放照片 Base64 或保证进程 RSS 下降指定字节数。
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
// 每页或每批使用;先部署包含方法的程序集,不依赖版本号猜测运行能力。
|
|
152
|
+
function clearFonts() {
|
|
153
|
+
try {
|
|
154
|
+
var result = V8.Image.ReleaseFontCache();
|
|
155
|
+
return result || { Code: 0, Msg: '字体缓存释放未返回结果' };
|
|
156
|
+
} catch (error) {
|
|
157
|
+
return { Code: 0, Msg: '字体缓存释放不可用,请核对程序集和服务重启状态' };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
var before = clearFonts();
|
|
161
|
+
if (Number(before.Code) !== 1) return before;
|
|
162
|
+
var drawn, after;
|
|
163
|
+
try {
|
|
164
|
+
drawn = V8.Image.Create({ Width: 640, Height: 160,
|
|
165
|
+
Text: '中文报表 / Report 2026', FontSize: 32, OutputFormat: 'png' });
|
|
166
|
+
} finally {
|
|
167
|
+
after = clearFonts(); // 不覆盖原始绘图异常。
|
|
168
|
+
}
|
|
169
|
+
if (!drawn || Number(drawn.Code) !== 1) return drawn || { Code: 0, Msg: '绘制未返回结果' };
|
|
170
|
+
if (Number(after.Code) !== 1) return after;
|
|
171
|
+
return { Code: 1, Data: drawn.Data, DataAppend: { FontCache: after.Data } };
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
普通单图无需每次清理,批量中文绘制出现原生缓存增长时才使用;禁止逐字符清理。
|
|
175
|
+
如果业务必须兼容旧部署,应显式返回未启用状态,不能把成功导出等同缓存释放成功。
|
|
176
|
+
验收须通过真实 API 测试连续绘图、清理后再绘图、失败时 `finally`、旧部署及并发;
|
|
177
|
+
观察冷生成内存,不能只测命中 PDF 缓存的请求。无系统字体 Linux 须单独回归。
|
|
178
|
+
|
|
133
179
|
## Create 生成图片
|
|
134
180
|
|
|
135
181
|
### 参数
|
|
@@ -64,7 +64,7 @@ try {
|
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
<!-- /microi-progressive:chunk -->
|
|
67
|
-
<!-- microi-progressive:chunk id=v8-security-010 sha256=
|
|
67
|
+
<!-- microi-progressive:chunk id=v8-security-010 sha256=556686f6250c75b35428b7283f79769b5a450cb9f67138f6483d2ea73f235751 -->
|
|
68
68
|
## 9. Token、终端会话与租户隔离
|
|
69
69
|
|
|
70
70
|
开发 Web、H5、UniApp、小程序、App、VS Code 或 MCP 客户端时,必须同时遵守 `microi-frontend-sdk/SKILL.md` 的 Token 协议:登录传 `_ClientType`,请求头传稳定 `did`,每次响应接收新的 `authorization`,并在浏览器/应用恢复前台时检查续签。
|
|
@@ -75,6 +75,11 @@ try {
|
|
|
75
75
|
- 收到 `TokenReplaced` 时先检查同一终端是否已有新 Token,避免并发旧响应误清新登录态。
|
|
76
76
|
- 用户提示可以显示过期时长、终端类型和租户 Key,但日志、Toast、URL、截图禁止输出完整 Token。
|
|
77
77
|
|
|
78
|
+
- 平台复制的 CLI/MCP 连接必须是独立开发会话,浏览器与开发工具分别续签、撤销。CLI、VS Code、MCP 共享导入 Token 时保留已有有效签名 `Did`;不得因宿主 Header 不同反复迁移,仅缺失或 `Empty` 的历史 Did 可受控补齐。客户端解码 JWT 只用于稳定请求头,身份仍由后端验签、租户和活动缓存确定。
|
|
79
|
+
- 登录、刷新、终端清理与吊销必须在同租户、同用户轮换锁内回读最新共享会话;鉴权或终端列表读取只清洗当前投影,不得整份回写旧 Token 列表,覆盖并发签发或复活已撤销终端。
|
|
80
|
+
- 真正吊销、超出服务端续签边界、共享登录缓存丢失时,必须有效登录后重新复制并安全导入连接;禁止用 `tokenlogin`、放宽期限或重建缓存绕过。`TokenReplaced` 先检查同连接共享 Token 是否已更新,不盲目重复刷新。
|
|
81
|
+
- HTTP 200 或空身份的 `Code=1` 不是认证成功;导入/登录/续签需核验有效 Token、非空用户 `Id` 和目标租户,随后真实初始化及状态回读。本次后端兼容修复支持已发布 CLI 6.2.1,不依赖另发 Agent 产品;源码加固、平台部署和工具产品发行分别记录。
|
|
82
|
+
|
|
78
83
|
### IP 高频拦截、受信 VS Code 独立阈值与解除
|
|
79
84
|
|
|
80
85
|
- `DataAppend.SecurityBlocked=true` 是服务端已可达但当前 IP 被临时拦截,不是网络断开。前端必须展示原始 `Msg`、`Reason`、`ExpiresAtUtc`、IP 和解除建议;不能把它转换成“后端 API 服务暂时不可用”。直接返回该结果的安全中间件必须在 CORS 之后。
|
|
@@ -166,6 +166,7 @@ outbox 编排放在接口引擎。密钥从当前租户 `V8.SysConfig.ServerPriv
|
|
|
166
166
|
| TCP | `V8.Tcp.Send/SendAsync/SendAndReceive/SendAndReceiveAsync`;原始字节与出站安全见 `v8-tcp-integration` |
|
|
167
167
|
| IoT 设备原连接下行 | `V8.IoT.Send({DeviceId,CommandId,FrameHex,ExpireSeconds})`;可信接口 Key、协议配置、Redis 路由及执行回执边界见 `v8-tcp-integration`,不包含厂家业务操作 |
|
|
168
168
|
| 图片 | `V8.Image.Create/Merge/Overlay/Watermark/Resize/Crop/Rotate/Flip/Draw/Convert/GetInfo/CreateQRCode` |
|
|
169
|
+
| 字体缓存维护 | `V8.Image.ReleaseFontCache()`,后端无参;批量中文绘制的页边界使用,返回缓存统计而非图片或 RSS;用法及部署检查见 `v8-image-processing` |
|
|
169
170
|
| Office | `V8.Office.ExportExcel/ExcelToList/ExportWord/ExportPowerPoint/SendEmail` |
|
|
170
171
|
| OCR | `await V8.OCR.Recognize({...})`;服务端租户配置与调用参数隔离,详见 `ocr-engine` |
|
|
171
172
|
| 文件 | `V8.HDFS`、`V8.Method.Upload/GetPrivateFileUrl` |
|
|
@@ -7,6 +7,8 @@ description: 设计、实现、配置、扩展和验收视觉引擎能力。处
|
|
|
7
7
|
|
|
8
8
|
# 视觉引擎
|
|
9
9
|
|
|
10
|
+
<!-- microi-progressive:begin -->
|
|
11
|
+
<!-- microi-progressive:chunk id=vision-engine-000 sha256=70053ac1db19e3d2ea23cc875a3de5fedb7c614d3c348572972309bf4a9ff4a8 -->
|
|
10
12
|
## 先读取相关规范
|
|
11
13
|
|
|
12
14
|
- 涉及完整表、字段、菜单和权限交付时,读取 `../microi-system-delivery/SKILL.md`。
|
|
@@ -132,7 +134,7 @@ v1.9.0 起禁止在巡检浏览器持续执行人员模型;手机仅采集、
|
|
|
132
134
|
检测请求串行、完成后间隔至少500ms,失败退避至10秒,画布复用。后台/卸载释放镜头,
|
|
133
135
|
暂停或切源中止检测与复核,忽略迟到结果。断流、过期帧、局部肢体和画面无效不能当无人。
|
|
134
136
|
手机大幅移动时工位统计标记中断/未知。60秒模拟负载测试不能冒充物理手机温控验收。
|
|
135
|
-
RF-DETR Large
|
|
137
|
+
固定RF-DETR legacy Large 560、YuNet/SFace和Qwen3-VL本地复核须分别锁定权重来源与许可;
|
|
136
138
|
预训练可直接推理不等于场景准确率达标,行为无正例或人脸无身份真值时不得声明90%。
|
|
137
139
|
通用节点Compose完整定义vision/behavior/media,默认启动vision+media,behavior为可选profile;API/PC继续复用,必须报告实际容器与复用原生服务的区别。
|
|
138
140
|
服务器准备入口为 `Microi.Server/tools/vision-deployment/deploy.py`,官网原位文档
|
|
@@ -154,12 +156,13 @@ CHOWN/FOWNER,不挂Docker socket;复用固定部署包、镜像与模型摘
|
|
|
154
156
|
FP16/量化候选必须与原精度逐图比较人数、框坐标和输出有效性,出现明显漏检不得发布。
|
|
155
157
|
异步行为模型需限制图片、上下文、输出与GPU占用;超时/格式错误保持未知,不能把复核链路可调用当作动作识别达标。
|
|
156
158
|
|
|
157
|
-
|
|
159
|
+
录像自 v1.9.9 起的旧节点本地/中继路径默认连续播放,保留可选“跟随分析播放(逐帧等待)”,旧单帧结果仅在原采样时刻±120ms绘制。v1.9.11可信公开对象时间轴走已登记HTTPS直连:固定每1秒媒体游标连续分析,默认准确率优先等待已接受且已回读的区段,可显式切换流畅预览,未知不计统计。原PTS结果到对应画面才建立真实纹理锚点;播放等待不覆盖手动暂停,seek只切显示窗口、不跳过后台分析秒。历史查看/切源关闭旧会话、取消原作业,晚回执不作用新会话;详见[可信录像时间轴、身份与私有图库](references/video-timeline.md)。
|
|
158
160
|
|
|
159
161
|
### v1.9.5 人脸定位与有界跟随
|
|
160
162
|
|
|
161
163
|
- 节点默认 YuNet 定位只产生 `faceBox/faceScore`,不因定位自动提身份模板。`evidenceKind=body/body-face/face` 区分证据:保留原人体 `box`,仅脸时 `box` 也必须是真实脸框,不补全身体。绘制优先合格脸框、否则人体;全帧 `valid=false` 保持未知清框。
|
|
162
164
|
- 摄像头显示层允许低负载灰度纹理跟随,不重新加载手机神经网络。迟到签名锚点必须按请求 FrameId/sequence 绑定原图,从原帧初始化并有界重放;禁止把旧框先套当前图再匹配。当前实现灰度长边256、8Hz、缓冲/锚点最多6秒,正反校验、纹理分数、几何与耗时预算全部通过才绘制;断流、遮挡、离开、低纹理、过期、暂停及换源及时清除。
|
|
165
|
+
- 节点1.9.8的独立快脸定位使用当前DiyToken和专用签名,单并发不排RF队列,最大640像素;只显示真实脸框,不提取模板/归档,不反向写人数、无人、身份或考勤。无脸不等于无人。
|
|
163
166
|
- 跟随只服务显示,不生成新人数/身份/考勤证据。仅脸可证明默认全画面有人,指定工位须人体脚点;脸下缘不能当脚点。历史有效片段占用率100%与当前待判断可以并存,但UI必须显示有效观测/覆盖范围,避免被理解为当前或全片100%。
|
|
164
167
|
- 回归必须覆盖3秒以上迟到锚点重放、真实像素移动/遮挡/离开、相机媒体时钟、暂停换源晚结果、face优先/body回退、320宽和短横屏明暗布局。模拟设备与桌面纹理耗时不能冒充物理手机温控。
|
|
165
168
|
|
|
@@ -233,7 +236,7 @@ FP16/量化候选必须与原精度逐图比较人数、框坐标和输出有效
|
|
|
233
236
|
|
|
234
237
|
### 视频巡检的手机连接与准确率门禁
|
|
235
238
|
|
|
236
|
-
|
|
239
|
+
手机默认选择摄像头;连接优先采用Bootstrap已验证登记的HTTPS节点,未登记时使用平台HTTPS中继(`edge=platform`),用户显式中继选择跨刷新保留,不能把电脑环回节点当作手机自身访问。复用 `platform-vision-edge-relay` / `platform-vision-edge-media` 与16个固定共享技术槽位,节点仅出站连接;受限访问密钥兑换DiyToken,Windows凭据用CurrentUser DPAPI保护。原始图片/特征仅进入短期加密缓存或节点有界内存,不记录在槽位表、浏览器结果或普通日志;官方包不包含节点凭据、运行槽位数据和客户录像。仍支持已登记HTTPS节点直连。
|
|
237
240
|
|
|
238
241
|
手机视频使用页面内控制和大画面保留跟随标注;不要调用iOS原生video全屏来承载SVG。画区时收起规则面板、定位取景区,控件至少44px,处理自动播放拒绝、横竖屏、相机关闭竞态。录像从节点原分辨率提帧,私有HLS只承担播放;分片上传每段SHA-256,不将整个长视频Base64放入V8。
|
|
239
242
|
|
|
@@ -269,3 +272,9 @@ FP16/量化候选必须与原精度逐图比较人数、框坐标和输出有效
|
|
|
269
272
|
Python 节点迁入 .NET 时必须分别列明媒体网关、FFmpeg、模型/GPU、行为模型资源及差分验证;未实际迁移不得声称已无额外运行依赖。
|
|
270
273
|
|
|
271
274
|
最终报告至少分开列出:源码测试、5 表/字段/索引、7 菜单、5 引擎/4 事件、微服务源码与构建哈希、商城包与版本、框架制品、目标节点版本、真实浏览器、PC/手机横竖屏布局、历史图片与纠错、真实图片素材来源、数据库命中、AI 回退、生鲜属性/价格来源、人脸同意、模型准确率和未执行的物理设备测试。
|
|
275
|
+
<!-- /microi-progressive:chunk -->
|
|
276
|
+
## 详细参考路由(渐进披露)
|
|
277
|
+
|
|
278
|
+
- [references/architecture-and-acceptance.md](references/architecture-and-acceptance.md):架构与验收
|
|
279
|
+
- [references/video-timeline.md](references/video-timeline.md):可信录像时间线与快速人脸定位
|
|
280
|
+
<!-- microi-progressive:end -->
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# 可信录像时间轴(v1.9.11)
|
|
2
|
+
|
|
3
|
+
公开对象登记最低依赖 API 8.8.8 的可信已完成上传证明,时间轴/独立快脸需要节点1.9.8和应用1.9.11接口字段。当前商城发布链未投影ServerMinVersion安装门禁;必须核验实际版本与能力,不能把文档版本要求当成已强制安装限制。
|
|
4
|
+
|
|
5
|
+
本节约束新路径;生效前须分别完成应用、接口/表字段、节点镜像与目标部署验收。旧节点本地媒体和中继兼容保留,不能仅升级页面就称新时间轴已部署。
|
|
6
|
+
|
|
7
|
+
## 来源与有界计算
|
|
8
|
+
|
|
9
|
+
- 正式示例播放文件属于租户明确授权的 FileServerBak 公开对象;浏览器播放零起点 H264 MP4。H265 原片另行保管,不能将原片可下载当作浏览器可解码。节点 `/data` 仅是有界计算缓存,不长期复制整片或把临时媒体目录当正式对象存储。
|
|
10
|
+
- 管理员通过 `platform-vision-media.RegisterObject`,从 `V8.Method.GetCompletedPublicUploadProof` 获取 Completed、公有回读通过的对象Id、存储绑定、完整SHA、大小和私有上传manifest分块SHA。URL和块摘要不能来自浏览器自行声明。目录、游标与逐帧投影分别用固定域封存。
|
|
11
|
+
- 节点只在固定API、当前DiyToken及 `VisionMediaGrant/1` 专用签名请求通过后使用 `VisionRemoteObject/1` 授权;绑定tenant/owner/object/session/generation/sequence/rules/model。首版 `timelineTransport=direct`,不经中继转运用户Token。
|
|
12
|
+
- Range固定HTTPS来源与规范ASCII路径;校验全公网DNS、TLS主机并固定连接IP,无重定向/任意URL。服务器可信1MiB或16MiB块逐块验SHA,32MiB缓存、64MiB作业总读取预算;失败保持明确错误,不能静默下载全片。
|
|
13
|
+
- 既有FFmpeg只访问本进程127.0.0.1随机路径桥;限定mov/dref关闭,桥无公开端口、无Docker服务、无任意代理。取消必须等待本次原生操作退出才释放共享推理锁,finally关闭本次桥与进程。
|
|
14
|
+
|
|
15
|
+
## 原时刻与展示
|
|
16
|
+
|
|
17
|
+
- 默认单帧窗口、一个在途请求,按0/1/2秒固定媒体游标连续分析,不按播放时钟跳点;协议最多8帧不是弱CPU应请求8帧。Grant约110秒、作业120秒,超时不延旧框;已Accept的帧仍通过ReadWindow权威回读。
|
|
18
|
+
- 准确率优先模式默认等待已接受、显示窗口已回读的连续区段;可显式切换流畅预览,未知不计入有效统计。无效但已分析的帧可观看,不变成有效观测;最后不足一秒按实际覆盖报告。手动暂停撤销播放意图,等待门不得用晚回执重开。seek仅切显示与ReadWindow,不重置分析游标;单在途回读只保留最新定位意图,最多3次退避,空回执不是成功。
|
|
19
|
+
- TimelineFrame包含实际PTS、requestedTime、frameId、imageSha256和完整来源绑定。平台逐序号CAS保存OriginalFrame/Result/State,不把前瞻统计写到当前session.ResultJson。浏览器只在原PTS到达时显示相应统计;实际解码帧回调建立纹理锚点,遮挡/断流/过期清除,不能把旧框硬贴当前画面。
|
|
20
|
+
- 准确优先暂停等待时也要投影已回读窗口:若视频仍停在同一已解码原时刻,采集该帧的灰度纹理后再恢复播放,不能只依赖播放中的帧回调。原时刻短窗口可直接绘制可信框;短窗口之外必须通过当前纹理跟随,不扩大旧框容差或修改考勤。
|
|
21
|
+
- 手机只用一个视频解码器、小灰度纹理缓冲与有界轮询,不下载神经网络。脸框独立验证;可跟踪同帧真实人体来辅助脸位移,但不能补造未检测到的脸、身体或身份。
|
|
22
|
+
- 切服务前固定原作业连接快照,取消不能请求新节点。倒退清未来行为候选;历史通过ReadSummary只读查看,不猜分析代次或继续旧考勤。恢复识别关闭本人的旧Active会话并新建,导出按权威历史摘要标明分析范围与覆盖率;ThroughTime以前最近已接受帧的累计摘要不等于完整事件清单,行为只含该最新帧复核。
|
|
23
|
+
|
|
24
|
+
## 独立快脸定位
|
|
25
|
+
|
|
26
|
+
节点1.9.8的 `/face-locations` 只接受已登记HTTPS直连与现有DiyToken。独立YuNet实例、单线程执行器和单并发锁,不排RF队列、不积压旧帧;最大640像素/1MiB。响应使用VisionFaceLocations/1独立签名域,绑定当前租户/用户/会话/原时刻/原图SHA,只输出真实脸框与质量;无身体、向量、裁剪、图库或员工身份。
|
|
27
|
+
|
|
28
|
+
前端最多单在途、最高2Hz,隐藏/暂停/换源取消,原图灰度纹理有界跟随。快脸叠层不得修改人数、无人、身份、行为或考勤;未检出脸不是无人。单模型70ms不能当作鉴权网络和RF并发后的端到端时延,需另测P95与物理手机温控。
|
|
29
|
+
|
|
30
|
+
## 身份、图库与候选
|
|
31
|
+
|
|
32
|
+
- Grant由会话明确 `enableIdentity && identityConsent` 决定identityPolicy;capturePolicy同时要求runtime.CanCaptureFaces和会话captureFaces未关闭。变更开关新建会话,不能沿用旧授权。
|
|
33
|
+
- Node同一JPEG复用私有MatchFaces/CaptureFaces;SFace只在已授权时运行。身份使用opencv-sface-2021dec,图库独立opencv-sface-2021dec-gallery-v1;图像/向量/__backend不进入公开作业或帧表。
|
|
34
|
+
- captureStatus为Disabled/NoEligibleFace/Completed/Unavailable,samplesAdded0..1;只有可信Operational故障可Unavailable。签名/权限/未知故障硬拒绝。CaptureFaces与AcceptFrame不是同事务;后者失败不意味着前者已回滚。
|
|
35
|
+
- 平台按权威人员/邀请目录重算准入,后台改名只覆盖当前显示名,不改历史封存;可变名字不能触发同序号全JSON冲突,身份Id/box/PTS/统计仍不可改变。没有录像发生时间时邀请时段保持Unknown,不用观看时间兜底。
|
|
36
|
+
- 已接受原帧后最多30秒一次低频行为候选,使用同JPEG和原PTS。共享单并发作业,最多600秒生命周期;ReviewTimeline绑定originalObservationSha256、behaviorJobId及原身份shape,仅追加Review投影,Candidate/Unvalidated与formalBehaviorCount0不变,不能改正式考勤。
|
|
37
|
+
|
|
38
|
+
## 许可与验收
|
|
39
|
+
|
|
40
|
+
固定旧权重来源是 onnx-community/rfdetr_large-ONNX@4988fbacee4aa815e43c2e0666377ab26bddf1e8(560输入)。`tile-small-v2`指小目标补充分块算法,不证明权重为Small。模型卡及当时官方COCO权重声明Apache-2.0;HF导出缺原始PT摘要与完整导出脚本,不能声称已证明每个张量溯源,也不能把其它代次规格自动归同一许可。逐模型保留来源/SHA/第三方通知。
|
|
41
|
+
|
|
42
|
+
协议/单测通过不等于目标NAS吞吐、手机温控、海康兼容或90%准确率通过。实际推理时延、解码Range预算、播放覆盖率、边框精度、行为分项正反样本、身份误接受/误拒绝分别验收。没有独立真值则保留未验收,不能用模型置信度或人工诊断少量图替代。
|