Files
lserp_cs_6.0/插件库/Lskj.AgentBridge/Deployment/CUSTOMER_ACCEPTANCE.md
T
2026-08-14 14:28:28 +08:00

257 lines
64 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 客户环境商用验收门禁
桥请求会话合同:CLI、Host 和 AstrBot 必须把数据库作用域指纹、用户、用户名、账套、子系统和管理员状态绑定为 v3 `sessionScopeToken`;能力、计划和执行请求缺失或不匹配时,ERP 服务端必须在任何业务查询/写入前拒绝。该令牌不是密码,也不能由模型生成或覆盖。
本文档是把当前 fail-closed 框架接入某个客户低代码配置的必做清单。未完成任何一项时,`purchase.invoice.create``hr.leave.resolve``hr.leave.create``hr.leave.submit` 必须保持未注册,不允许通过改 `enabled=true` 绕过。
## 0. 旧 ERP 与 CLI 构建取证
禁止直接使用共享 `Release` 目录中的历史二进制。先从经过代码审查、无未提交文件且与桌宠包 `BUILD-VERIFICATION.json/sourceCommit` 相同的提交运行 `Build-LegacyErpAcceptance.ps1`。输出目录必须是新目录;同时提供经过制品库审批、与现有 `Xilium.CefGlue 87.1.1` 配套的 `cef.redist.x86.87.1.13.nupkg`,其 SHA-256 必须为 `34dfe2504c1ffaef02eab1f38578701b045439349997b6465fd5dd6659fab021`。脚本会创建提交级隔离克隆,按 `Release|Mixed Platforms` 的解决方案映射重建 `lserp-cli``Ls_ERP``Lskj.AgentBridge``Lskj.CommandKernel` 及依赖,复制并逐哈希复核完整原生 CEF 运行时,并验证 .NET Framework 4、最终 EXE 的 x86/`32BITREQUIRED`、ERP `LargeAddressAware`、DevExpress 15.2 和固定依赖契约。脚本还会在任何 Authenticode 签名前扫描 `Ls_ERP.exe``lserp-cli.exe` 和顶层 `Lskj.*.dll` 的 ASCII/UTF-16 字符视图;发现成对硬编码 SQL 用户名/口令时只返回 `legacy_runtime_hardcoded_sql_credential:<文件名>` 并终止,不回显凭据值。该门禁不代替客户制品库的全量秘密扫描、SBOM 和恶意软件检查。CEF 87 仅是遗留兼容基线;完成受支持版本升级或客户安全负责人书面风险接受前,禁止该内嵌浏览器访问公网及其他不受信任页面。
最终构建必须向脚本提供客户发布证书指纹和 HTTPS RFC3161 时间戳地址,由脚本在生成哈希证据前签署 `Ls_ERP.exe``lserp-cli.exe`、AgentBridge、CommandKernel 和 Core。桌宠侧还必须用同一客户批准证书签署 `Lskj.AgentPet.Host.exe``Lskj.AgentPet.Host.dll``Lskj.AgentPet.Host.Core.dll`,预检与启动时通过 `-HostCertificateThumbprint` 固定预期签发者。保留 `LEGACY-BUILD-EVIDENCE.json``MSBUILD.log`、签名后全部逐文件哈希、安装包哈希和回滚版本;证据生成后不得再修改 Runtime 文件。`Verify-LserpCommercialPackage.ps1` 必须同时传入最终 ZIP 的 `-PackageArchivePath`、解包目录、构建目录、证书指纹、`-RolloutPolicyPath``-RolloutCustomerId` 并通过;报告中的 `package_archive_binding` 必须证明 ZIP 与解包目录同属一份逐文件清单,`erp_rollout_policy` 则证明目标 ERP 进程实际加载的发布策略哈希和客户 ID 与现场文件一致。构建通过只证明产物契约,不证明客户事务、权限或工作流正确。
## 1. 环境与秘密
商用桥启动前必须先完成命令发布范围签收。把 `command-rollout.example.json` 复制到安装包外的客户受控目录,保持 `schemaVersion=1.1``defaultAction=deny`,把根级 `databaseScopeFingerprint` 替换为本次人工核准的当前数据库作用域,只列出本客户已经注册且获准发布的命令;每条规则精确绑定命令版本、原 ERP `requiredPermission`、账套、子系统及 `all_authorized`、精确内置管理员或精确用户。旧 ERP 的 `GroupId` 只是菜单分组,不是可信角色 ID,不能写入自创“角色映射”扩大权限。最终文件只允许部署人员修改、ERP 用户读取,且不得是链接。以下变量必须由批准的启动器在启动签名 ERP 进程前同时注入;SHA-256 针对文件原始字节,客户部署标识是制品系统分配的非秘密稳定 ID:
```powershell
$rolloutPath = 'C:\ProgramData\Langsu\AgentBridge\command-rollout.json'
$rolloutSha256 = (Get-FileHash -LiteralPath $rolloutPath -Algorithm SHA256).Hash.ToLowerInvariant()
$env:LSERP_AGENT_ROLLOUT_CONFIG = $rolloutPath
$env:LSERP_AGENT_ROLLOUT_SHA256 = $rolloutSha256
$env:LSERP_AGENT_ROLLOUT_CUSTOMER_ID = 'CUSTOMER-001'
$env:LSERP_AGENT_BRIDGE_ENABLED = '1'
# 从这个已批准的启动器进程启动最终签名的 Ls_ERP.exe。
```
- 只在客户 Windows 10/11 测试终端和可恢复的 SQL Server 验收库上执行写入测试。
- ERP、AgentBridge、AstrBot 同机模式必须运行在同一个 Windows 用户边界;当前宿主、商用启动器和预检只接受 loopback 地址。中央 AstrBot 必须先实现客户端主动出站、双向设备身份的 Agent Gateway,不能暴露命名管道;Gateway 尚未交付前,任何远程 HTTP/HTTPS 地址都必须失败关闭。
- 在 AstrBot 专用服务账号中用轮换后的 MiniMax Key 运行包内 `AstrBotPlugin\verify_minimax_vlm_contract.py`,区域必须与采购套餐一致。探针只能发送内置无客户数据图片,报告必须显示官方 0.0.4 合同提交、`MM-API-Source`、固定端点和 `passed=true`;将报告 SHA-256 写入法务/安全复核的 MiniMax 服务证据。不得使用聊天中曾暴露的 Key,也不得用真实客户发票代替合成探针。
- 由受控管理员只在隔离验收进程中读取实际 `lserp.agent.<PID>.<bridgeInstanceId>` 管道名,再让同机第二个普通 Windows 用户直接连接,并从另一台电脑以与 ERP 相同的域账号通过远程命名管道连接;两者都必须在发送协议帧前得到访问拒绝,ERP 不得产生桥审计、计划或确认框。不得退化回可预测的无代际 `lserp.agent.<PID>`。同机 ERP 用户及 LocalSystem 的受控健康检查必须成功;用 ACL 检查工具确认保护继承已开启、Owner 为启动 ERP 的用户、存在 `NetworkSid/AnonymousSid` 拒绝,且不存在 Everyone/Authenticated Users 允许项。
- 在 ERP 同一 Windows 用户下先备份并替换发现文件,让测试进程创建相同协议名的假管道,同时让真实 ERP PID 和启动时间仍保持有效。最终签名 CLI、桌宠宿主和 AstrBot Tool 都必须在发送任何请求字节前返回 `bridge_server_identity_mismatch`,假服务端观察到的请求字节数必须为 0,ERP 不得产生计划、确认框或业务审计;恢复原子发布的真实发现文件后,三条链的只读健康检查必须成功。
- 在保持同一个 ERP EXE/PID 和进程启动时间的条件下,先生成一个只读计划,再模拟退出登录或调用桥停止/重建。新发现文件的 32 位小写十六进制 `bridgeInstanceId` 必须与旧值不同,新管道必须从 `lserp.agent.<PID>.<旧bridgeInstanceId>` 变为 `lserp.agent.<PID>.<新bridgeInstanceId>`;把旧发现文件保留到新桥开始监听但新发现文件尚未发布的窗口,旧客户端只能得到连接失败,不能进入新桥。独立 CLI 重新派生的 v2 `clientSessionId` 必须变化,旧计划不能执行。保持旧 `clientSessionId` 的桌宠 Host 与 AstrBot Tool 必须在打开新管道或发送业务请求前返回 `erp_bridge_instance_changed`,且零确认、零数据库调用、零完成审计;关闭旧桌宠并通过启动器创建全新会话后,只读健康检查才恢复。发现代际不得进入模型上下文、业务预览或验收报告。
- 客户终端无论单开或多开 ERP,桌宠都必须由 `Start-LserpAgentPet.ps1` 启动并生成 `lserp-pet-p<PID>-s<启动Unix秒>-c<32位会话作用域令牌>-<32位随机数>` 会话;作用域令牌必须按固定合同共同绑定人工核准的数据库作用域指纹、用户编号、用户名、账套、子系统和管理员布尔值。宿主、AstrBot Prompt 和三个 ERP Tool 必须拒绝缺 PID、缺启动时间/作用域令牌或仅匹配前缀的旧式会话。宿主直连桥和三个 Tool 还必须在目标操作前后执行严格 `context.get`,初始不符以 `erp_session_scope_mismatch` 阻断,期间切换以 `erp_session_scope_changed` 丢弃结果。商用预检、桌宠启动以及同一组 CLI `bridge plan/execute` 必须使用相同的 PID、数据库作用域指纹、用户编号、用户名、账套、子系统和管理员布尔值;受限 CLI 的每个命令都必须收到六项显式预期范围参数,并独立执行初始范围校验及目标调用前后复核。预检会用最终签名 CLI 实际执行只读 `bridge health`;未指定目标、缺少任一范围参数或目标启动实例变化时必须失败关闭,禁止按发现文件时间自动切换账套。
- ERP 内部数据库执行边界也必须独立复核同一作用域:采购/请假读写和通用低代码 Lookup/新增/更新在过程调用前后,以及任何成功写事务 `Commit` 前,都要把请求中的用户(就绪查询可省略用户)、账套、子系统、数据库指纹与当前 `ERPInfo`、同一个 `SqlHelper._connection` 实例、实际服务器和数据库逐字比对。现场验收至少要覆盖切换用户/账套/子系统、替换连接实例、同名库换服务器和连接中途换库的负例;读取必须丢弃,写入必须回滚并返回 `erp_session_scope_changed``erp_database_session_changed`,不能仅依赖桌宠调用后的 `context.get`
- 在同一 ERP 登录会话分别保持配置端点不变但替换到另一台服务器上的同名验收库、保持实际连接不变但修改配置端点,以及重新登录原库三种场景。前两种场景必须因“配置端点 + `DbConnection.DataSource` 实际端点 + 实际数据库 + 提供者”作用域指纹变化而拒绝旧计划、旧验收证据和旧幂等重放;重新登录原库只能重新规划,不能复用重启前计划。任何响应、模型上下文和日志都不得回显服务器、库名或连接串。
- 分别验证缺少三个发布变量中的任意一个、篡改配置一个字节但沿用旧 SHA-256、客户 ID 不一致、`defaultAction=allow`、JSON 含注释/重复/未知字段、规则引用未注册命令、命令版本或 `requiredPermission` 漂移;每个负例都必须允许普通 ERP 继续运行但不产生 AgentBridge 发现文件。正例启动后,以范围内/外账套、子系统、普通用户、同名假管理员和精确内置管理员检查 capabilities;范围外命令必须隐藏,直接 plan/已有 plan 的执行复核必须返回 `command_rollout_denied` 且零确认/零数据库调用。修改文件或环境变量在旧进程中不得热生效,重启后旧计划必须消失。
- 使用最终签名 CLI 对精确 ERP PID 执行 `bridge health`,核对 `rolloutPolicy.configured=true``failClosed=true``defaultAction=deny`、客户 ID、数据库作用域指纹、规则数和现场文件 SHA-256。该对象只能有这七个字段,不得返回配置路径、账套、子系统、用户、权限或规则内容。随后给商用预检传入同一文件、客户 ID 和完整预期会话,`erp_rollout_policy``erp_session_scope` 必须通过;换发布文件、数据库、用户、账套、子系统、客户 ID 或 ERP PID 都必须失败关闭,且桌宠不得启动。
- 连续冷启动 ERP 20 次,在每次发现文件出现后立即执行绑定该进程的 `bridge health`,不得出现发现文件已发布但监听尚未就绪。再让 4 个本地测试客户端只连接不发送,确认 15 秒后全部连接槽恢复;关闭 ERP 时接收线程必须在 2 秒内退出。发送畸形 UTF-8 帧必须得到 `invalid_utf8` 或被安全断开,且不得产生业务计划、确认框、数据库调用或残留发现文件。
- 在验收 ERP 启动前设置 `LSERP_AGENT_DISABLED_COMMANDS=module.navigate`,确认该命令不出现在 capabilities,直接规划返回 `command_disabled` 且零确认/零数据库调用;清除后重启才恢复。再填入一个格式合法但当前未注册的命令名,桥也必须拒绝发布,不能静默忽略拼写错误。分别把每分钟限流设为 2、会话状态容量设为 2,验证第三个同会话请求返回 `bridge_rate_limit_exceeded`、第三个并行会话返回 `bridge_rate_state_capacity_exceeded`,一分钟/五分钟边界后恢复。再让一个受控只读测试命令连续返回白名单 `workflow_database_error` 达到阈值,确认命令从 capabilities 隐藏并返回 `command_circuit_open`;输入错误、权限拒绝和用户取消不得触发熔断,冷却后只能有一个半开探测。`health.operationalPolicy` 只能出现阈值与计数。核对进程审计中有首次拒绝、`command_circuit_opened` 和恢复后的 `command_circuit_closed`,关联 ID/ERP 作用域正确且没有 payload;同一拒绝一分钟内重复 100 次不得增加 100 行。任一运维环境变量含空项、重复命令、非法整数或越界值时,ERP 可以继续启动,但桥不得发布发现文件。
- 验证每个并行 ERP 启动实例只创建自己的 `%LOCALAPPDATA%\Langsu\Lserp\AgentBridge\Audit\audit-p<PID>-s<UTC ticks>.jsonl`,没有共享追加或覆盖。模拟只读目录、非换行截断尾部、64 MB 单文件门限、512 MB/256 文件待归档门限时,桥必须在发布发现文件或生成新计划前失败关闭;归档只能移动已经退出的实例日志,禁止自动删旧日志来绕过门限。
- AstrBot Key 只授予 `chat + file` scopes,存放在 Windows 凭据管理器;MiniMax Key 只由 AstrBot 服务账号的秘密管理器注入。
- 已在聊天、日志、脚本或工单中暴露过的 Key 一律先撤销再创建新 Key。
-`user_id=1` 且名称精确为“管理员”的内置账号验证诊断能力;另外创建或选择一个名称同为“管理员”但 ID 不为 1 的隔离测试账号,确认其 `context.isAdministrator=false`,且 `modules diagnose`、初始化追踪和无菜单权限读取均返回 `administrator_required`/权限拒绝。不得通过复制显示名获得 Agent 管理权限。
- 客户机 WebView2 Evergreen Runtime 必须为 `151.0.4129.50` 或更高版本,与宿主锁定的 Release SDK `1.0.4129.50` 满足完整 API 兼容要求;组策略暂停自动更新、注册表版本无法解析或版本过低时,商用预检必须返回 `webview2_version_unsupported`
- 在 Windows 10/11 实机分别以 100%、125%、150% 和 200% 缩放,并覆盖主副屏不同 DPI,验证透明背景、拖动把手、标题栏拖动、业务按钮点击和退出;不得出现黑色矩形、点击区域变成拖动区、窗口移屏后裁切或退出后残留桌宠/WebView2 进程。该项只能由实机验收记录证明,跨平台编译不能替代。
- 鼠标在宠物主体上连续悬停约 480 ms 后必须展开对话面板,悬停展开不得抢走 ERP 当前输入控件的键盘焦点;悬停展开后的第一次点击必须保持面板展开并聚焦聊天输入框,再次点击才可收起。先在 ERP 切换两个不同模块,每次展开后标题必须刷新为当前活动模块,不能沿用上次缓存;只读上下文刷新失败时不得伪造模块信息或阻断后续聊天。该项必须在 Windows 实机用可输入控件和两个有权菜单留存验收证据。
- 桌宠标题下方必须显示当前受信任 ERP 会话范围的账套、子系统、用户和数据库指纹前 12 位证据,不得显示服务器、库名、连接串或完整数据库指纹。先生成一条可执行计划,再分别切换数据库、ERP 用户、账套和子系统;每种情况下点击执行都必须在向 ERP 发送执行请求前重新验证范围、作废旧计划并提示重新生成预览,且数据库调用、确认框和完成审计均为零。恢复原范围后也必须重新规划,不能复用旧计划;聊天与只读重新发现能力仍应可用。
- 桌宠必须提供“录入采购发票”“申请请假”“当前界面能做什么”和“只读诊断当前界面”固定快捷入口。没有附件或完整采购明细时,采购入口只能提示补充材料,不得产生写计划;请假入口必须询问用户原始日期表达与时段、类型、原因和是否提交审批,不得自行换算日期或补全提交意图。“检查业务能力”只在受信任上下文确认当前身份为 ERP 内置管理员时显示;普通用户和同名非内置管理员均不得看到。即使按钮可见,直接调用 `adapters.status` 仍必须由 ERP 服务端权限复核,且结果只能包含稳定阻断代码、受控说明和下一步,不得泄露配置证据、SQL 或物理字段。
## 2. 低代码元数据取证
旧 ERP 正常登录会调用 `P_Login_pr`,并可能登记在线会话、IP/MAC 或补老库兼容字段,所以“业务查询只读”不等于“整个连接过程零写入”。若客户只批准对目标库做零写入摸底,禁止先运行直连 `lserp-cli --ledger/--user`。应由 DBA 创建没有数据库/服务器角色、没有数据库级 DML/DDL/EXECUTE、没有任何对象或 Schema 写/执行权的专用 SQL 账号,并在 Windows PowerShell 5.1 运行:
```powershell
$credential = Get-Credential -UserName <客户SELECT-only SQL账号>
.\Invoke-LserpSelectOnlyCatalogSnapshot.ps1 `
-Server <证书名称匹配的SQL Server TLS端点> `
-Database <目标数据库> `
-Credential $credential `
-OutputPath D:\Acceptance\Evidence\select-only-catalog-new.json
```
脚本固定使用系统信任链校验的 TLS、`ApplicationIntent=ReadOnly`、关闭连接池和持久凭据;不提供跳过证书验证的参数。它用同一固定 SELECT 在目录读取前后各检查一次 `sysadmin/db_owner/db_ddladmin/db_datawriter`、服务器与数据库权限、每张用户表/视图、过程/函数和 Schema 的有效写/执行权,任一次非零即返回 `database_principal_not_select_only` 且不发布文件。两段嵌入查询已由锁定的 ScriptDom `TSql100Parser` 证明全部 AST 顶层语句都是 `SELECT`;只读 `sys.*`,不执行过程、不读取业务行。采集开始和结束还会把磁盘脚本 SHA-256 与 PowerShell 实际加载的完整 AST 文本 SHA-256 比较,运行中替换脚本返回 `tool_source_changed`。新建 ACL 文件只保留服务器、库、主体和目录成员的 SHA-256、兼容级别与对象计数,不保留原始名称或口令。该快照只能证明 SQL 目录摸底没有使用可写主体,不能证明 ERP 用户权限、菜单、账套、子系统或业务过程正确。
采集后立即用最终 CLI 离线运行 `lserp-cli adapters verify-catalog-snapshot --input <snapshot.json> --profile <客户画像.json> --tool-sha256 <随包采集脚本SHA-256>`。验证器只接受 `schemaVersion=1.1`,拒绝未知/重复字段、链接路径、超过 16 MB、过期/未来时间、脚本哈希不符、缺少权限前后双检、脚本字节不稳定、权限/TLS/安全声明不符、目录哈希重复/乱序或集合摘要篡改,并把画像关键目录按同一小写不变区域规范转换为哈希比对。旧 1.0 快照必须重新采集。输出不得出现原始服务器、库、主体、表、列或过程名;即使全部匹配也固定 `registrationReady=false`
正式现场推荐用随包包装器一次完成采集与离线验证,避免实施人员手工复制错误哈希或误用另一份 CLI。所有哈希均从已审查发布记录取得,SQL 口令仍只存在于交互式 `PSCredential`
```powershell
$credential = Get-Credential -UserName <客户SELECT-only SQL账号>
.\Invoke-LserpSelectOnlyProfilePreflight.ps1 `
-Server <证书名称匹配的SQL Server TLS端点> `
-Database <目标数据库> `
-Credential $credential `
-ProfilePath .\customer-profile.json `
-ExpectedProfileSha256 <画像原始文件SHA256> `
-CliPath D:\Acceptance\legacy-erp-build\Runtime\lserp-cli.exe `
-ExpectedCliSha256 <最终签名CLI的SHA256> `
-ExpectedSignerThumbprint <CLI签发证书40位指纹> `
-ExpectedCollectorSha256 <随包采集脚本SHA256> `
-SnapshotOutputPath D:\Acceptance\Evidence\select-only-catalog-new.json `
-ReportOutputPath D:\Acceptance\Evidence\select-only-profile-preflight-new.json
```
包装器会锁定画像、采集器和 CLI,复核 Authenticode,且报告只保留制品哈希、数据库作用域哈希、匹配布尔值和缺失目录成员哈希。目录漂移时报告为 `passed=false` 并返回非零;工具、签名、协议或安全证明异常时不会保留未验证快照。它不运行旧 ERP 登录、不执行存储过程、不读取业务行,也不会把通过结果解释为可注册写命令。
完成客户批准的正常 ERP 登录后,分别在采购、请假和诊断所属子系统执行只读业务检查。采购与请假使用实际获权业务用户,诊断使用管理员;即使 ERP 可以在同一进程切换子系统,也必须为每个作用域重新采集独立审批、预检和交接文件,禁止把切换前后的上下文拼成一份证据:
先在客户机本地由实施人员从批准的 ERP 启动记录/只读会话交接中取得本次 PID、64 位 `databaseScopeFingerprint`、用户编号、用户名、账套、子系统和管理员属性,并由人工确认它们属于本次批准范围;不得猜测、从模型补全或把原始上下文发送给 AstrBot/MiniMax、聊天或普通日志。桥/工作流命令(包括独立签名管理员验收工具 `lserp-cli.exe`)不接受只传 PID 的引导调用;需要本地复核时,必须完整传入 `--erp-process-id` 加六个 `--expected-*` 范围参数,例如 `lserp-cli.exe bridge context --erp-process-id <PID> --expected-database-scope-fingerprint <64位小写SHA-256> --expected-user-id <用户编号> --expected-user-name <用户名> --expected-account-book <账套> --expected-subsystem-id <子系统编号> --expected-is-administrator <true|false>`。该调用只验证已批准的预期范围与当前 ERP 上下文逐项一致,不能作为“先连接后猜测范围”的来源。受限 `lserp-agent-cli.exe` 第一次调用也必须携带同一完整范围。正式现场应把 `field-readonly-validation.example.json` 复制到包外受控目录,填写并独立批准上述预期范围、CLI/ERP/预检脚本哈希、发布策略和 `purchase/leave/diagnosis/support` 到客户实际模块编号的映射,再用输入文件 SHA-256 调用 `Invoke-LserpFieldReadOnlyValidation.ps1`。先带 `-ValidateInputOnly` 生成不执行预检的脱敏交接报告,再换新输出文件去掉该开关;包装器不会自动采信 Bridge 自报范围,会把审核值完整传给下列底层只读预检及每个受限 CLI 子进程。审批最长 24 小时,模板默认拒绝,且不允许任何数据库凭据字段。不同 ERP 身份应各自生成审批文件和预检证据。
以下直接调用只作为包装器所绑定的底层参数对照;不得用手工命令替代已批准输入的哈希交接:
```powershell
$cli = 'D:\ApprovedPackages\Lserp-AgentPet-@LSERP_PACKAGE_VERSION@-win-x64\Host\lserp-agent-cli.exe'
$erp = 'D:\Acceptance\legacy-erp-build\Runtime\Ls_ERP.exe'
$rollout = 'C:\ProgramData\Langsu\AgentBridge\command-rollout.json'
.\Invoke-LserpReadOnlySessionPreflight.ps1 `
-CliPath $cli `
-ExpectedCliVersion @LSERP_PACKAGE_VERSION@ `
-ExpectedCliSha256 (Get-FileHash -LiteralPath $cli -Algorithm SHA256).Hash `
-ExpectedSignerThumbprint <40位客户发布证书指纹> `
-ErpProcessId <当前ERP进程PID> `
-ExpectedErpSha256 (Get-FileHash -LiteralPath $erp -Algorithm SHA256).Hash `
-ExpectedDatabaseScopeFingerprint <已人工核准的64位数据库作用域指纹> `
-ExpectedUserId <当前ERP登录用户ID> `
-ExpectedUserName <当前ERP登录用户名> `
-ExpectedAccountBook <当前ERP账套> `
-ExpectedSubSystemId <当前ERP子系统ID> `
-ExpectedIsAdministrator $false `
-ExpectedRolloutCustomerId <客户部署标识> `
-ExpectedRolloutPolicySha256 (Get-FileHash -LiteralPath $rollout -Algorithm SHA256).Hash `
-ModuleCodes @(<采购模块或导航编号>) `
-RequirePurchaseWorkflow `
-OutputPath D:\Acceptance\Evidence\purchase-readonly-session-preflight-new.json
```
请假会话只传请假模块并只打开 `-RequireLeaveWorkflow`;诊断会话传入四类故障证据涉及的全部去重模块,只打开 `-RequireDiagnosisWorkflow`,且 `-ExpectedIsAdministrator` 必须为 `$true`。三份报告可以记录相同或不同 PID,但用户、子系统、模块和时间戳必须各自匹配,能力表中非当前角色命令只能作为非必需能力出现。
脚本只接受 Windows PowerShell 5.1、最终签名且未变化的受限 `lserp-agent-cli.exe` 和 ERP 文件句柄;它会先实际运行 `version`,逐字段确认版本、`bridgeOnly=true``databaseDirectAccess=false``sessionSource=current_logged_in_erp_process`,因此管理员 `lserp-cli.exe` 不能冒充现场运行时。它要求指定 PID 的主模块名精确为 `Ls_ERP.exe`,且 ERP 哈希和签发者与最终构建证据一致,前后还会复核 PID 启动时间、路径及文件哈希未变。`-ExpectedUserId``-ExpectedUserName``-ExpectedAccountBook``-ExpectedSubSystemId``-ExpectedIsAdministrator` 都是必传值,第一次读取 `bridge context` 时即与当前 ERP 会话逐字匹配;任一不符都会在能力和动态模块读取之前以 `expected_session_scope_mismatch` 失败,诊断工作流还会拒绝非管理员预期值。所有子进程参数在运行时再次经过精确只读白名单,只能调用本地 `version``bridge health/context/capabilities` 与风险固定为 `read``executionAllowed=false``bridge plan module.parameters`。它不接收数据库地址、库名、账号口令或连接串,不建立数据库连接,不调用 `bridge execute`,也不读取业务行。`schemaVersion=1.5` 报告使用 `CreateNew`,必须包含 `cli_runtime_identity``rollout_database_scope``expected_session_scope``dynamic_module_execution_contracts` 检查;除 ERP/运行时 CLI 版本、哈希与签发者、会话标识的域分离 SHA-256、数据库作用域指纹和能力版本/风险外,只保留模块合同/配置指纹、scalar/单值 Lookup/unsupported 计数、严格载荷策略与可编辑/必填参数数量、经审核的原生保存族/指纹,以及新增/修改的就绪或阻断状态。载荷参数 ID 必须与当前合同中的可编辑/必填集合逐项一致,基础档案与单据的明细行约束必须匹配,单据通用修改必须保持关闭;字段标签、业务值、连接信息、物理字段和临时输入不会保留。旧 1.4 及更早报告不能进入当前总验收。客户适配器尚未注册的第一次动态参数发现可以省略对应 `-Require*Workflow` 开关,但这种报告不证明该工作流可用;完成适配器、签名证据和默认拒绝发布策略后,各会话必须用新文件及自身唯一的工作流开关再次通过。该报告始终固定 `productionWriteAuthorized=false`,不能代替后续事务 UAT。
```text
lserp-cli adapters inspect purchase <客户采购发票模块编号>
lserp-cli adapters inspect leave <客户请假模块编号>
lserp-cli adapters export-review purchase <客户采购发票模块编号> --output <purchase-review.json>
lserp-cli adapters export-review leave <客户请假模块编号> --output <leave-review.json>
lserp-cli adapters verify-review --input <purchase-review.json>
lserp-cli adapters verify-review --input <leave-review.json>
lserp-cli adapters validate-fields purchase --input <purchase-mapping.json>
lserp-cli adapters validate-fields leave --input <leave-mapping.json>
```
人工审核导出的模块名、模块类型、主/明细表与每个候选字段,并校验复核包 `contentSha256`。复核包绑定当前账套、子系统和管理员用户,且 `registrationReady` 固定为 `false`。候选评分和内容哈希仅是证据,不是自动绑定;只有名称相似但业务含义未证实时必须停止。客户 1.2 画像中本工作流每个阻断项只有在对应证据真实完成并签字后才能从 `open/resolution=null` 改为 `resolved`;此时必须填写代码指定的 `evidenceArtifact`、最终制品原始字节 SHA-256、批准人和 UTC 批准时间。固定阻断码不能删除、替换或追加;签发脚本和 ERP 运行时都会要求本工作流 `approved=true/openBlockerCount=0`,并把每个解决哈希与签名清单中即将使用的字段映射或写集成文件逐字节复核。采购还要同步批准目标模块选择。采购与请假可独立验收,不能为了启用其中一条而伪造另一条状态。
对普通用户有权限的基础档案和单据模块分别执行 `lserp-cli modules parameters <moduleCode> --ledger <账套> --user <用户> --subsystem <子系统>`,并通过同一已登录 ERP PID 计划 `module.parameters` `1.1`。两路结果必须来自当前数据库低代码配置,包含全部可见主表/明细参数的不透明 `parameterId`、类型、格式、必填、只读、默认值、Lookup、`inputMode``requiresDedicatedAdapter``maximumEncodedBytes``LimitLen`ERP 进程默认编码字节数)和数值 `maximumDecimalPlaces``DataDec`,缺省 2)标记,但不得出现表、SQL、物理字段、Lookup 键/显示列或连接信息。普通标量必须是 `scalar`,所有单值选择控件即使配置数据源为空也必须是 `lookup-single` 并停止于唯一解析门禁;多选、设备、动态 SQL、计算、回填多行、单据来源以及未识别类型必须是 `unsupported`、不可编辑且要求专用适配器。复选框合同只接受小写 `true/false`,受信任写 XML 中必须是旧 ERP 的 `1/0`。换用户、账套或子系统后 `contractFingerprint` 必须变化;仅改变数据库返回字段行顺序不得变化;修改任一控件配置、长度/小数位、可见性、必填、默认值、Lookup、主/明细定义或 SQL 钩子后旧合同必须失效并要求重新发现。再用合同按 `parameter_entries_v1` 计划 `module.record.prepare-create`:正常纯标量主表/明细输入只能返回 `draft` 参数预演,跨范围/漂移、未知、重复、只读、密码/图片、复杂或未知控件、错误布尔/整数/数值/日期、超 `LimitLen`、超 `DataDec`、非法约束配置、缺少必填和未解析 Lookup 分别必须失败关闭,响应不得出现物理字段或 SQL。通用事务适配器尚未验收时必须明确返回 `genericWriteExecutionAvailable=false`,该计划不能被保存或执行,不得弹 ERP 原生确认、占用幂等键或调用数据库写入。
现场所说的“传递全部参数”必须分成两层验收:`payloadContract.masterParameterIds/detailParameterIds` 必须逐项覆盖当前合同的全部可编辑参数,`required*ParameterIds` 必须精确等于其中无 ERP 默认值的必填子集;具体业务载荷必须携带这个必填子集,可显式携带其他可编辑值。含当前低代码默认值的参数允许从业务载荷省略,让服务器默认逻辑生效;不得为追求“数量齐全”而传空串覆盖默认值,也不得把只读、系统编号或专用适配器字段加入模型载荷。固定事务过程必须使用当前配置指纹二次验证这两个集合和服务器默认行为。
完成动态新增/修改适配器验收后,分别通过 `module.record.resolve-create → module.record.create``module.record.resolve-update → module.record.update` 取得可信写预览。桌宠必须把新增主表字段、每行明细及修改前/后值结构化展示,并在用户滚动核对全部内容前禁用执行按钮;任何未知键、物理字段名、重复不透明参数 ID、明细行号不连续、控制字符、越界值、顶层与 `data.preview`/`parameterPreview` 不一致、合同或适配器摘要无效都必须禁止执行。使用空字符串、多行文本、512 个主表字段、1000 行明细、5000 个总值和 512 个修改字段验证允许边界,再各增加一项验证失败关闭;确认后修改权限、配置、Lookup、记录快照或验收证据时不得沿用旧计划。
另选取模块返回控件做模式验收:`116/117/160/161``IsRadio=1` 时必须是 `lookup-single`,在缺列、空值或 `0` 时必须是 `unsupported``42/171/172` 必须保持显式单选,`43` 与扩展多字段回填 `173/174` 必须要求专用适配器。只改变 `IsRadio` 后旧 `contractFingerprint` 必须失效,旧 Lookup 凭证和计划均不得复用。
选取半天日期控件 `445`:公开合同只接受 `yyyy-MM-dd|am-or-pm`,预演必须拒绝 `yyyy-MM-dd 上午/下午`;进入受信任事务适配器的值必须反向转换为旧控件真实格式。上午、下午各验证一次,并确认合同预览仍显示用户可理解的公开值而不暴露物理字段。
禁止人工直接改写上述状态。使用同一客户 ERP 的内置管理员执行 `lserp-cli adapters prepare-profile-activation <purchase|leave>`,同时提供最终字段映射、已通过的只读契约证据、完整写集成报告、运行配置哈希、源码提交和商用包哈希;CLI 通过在线字段与关键目录复核后只新建未签名候选。候选仍固定不可注册,必须继续完成工作流签名清单、V2 验收证据写入和 V3 运行时就绪核对。
在进入上述在线步骤前,先离线执行 `lserp-cli adapters activation-checklist --input <客户画像.json>`。它必须用非零退出码逐项列出尚未完成的稳定阻断码、所需证据类型和固定下一步,不得输出数据库名、物理字段、画像证据正文或 SQL;即使全部阻断项关闭并返回 0,输出仍必须保持 `activationAllowed=false/registrationReady=false`,不得被部署脚本解释为已经可以写库。
桌宠失败恢复也必须作为客户 UAT 门禁,不得只验证成功路径:
- 采购预览生成后,由验收人员在受控 UAT 数据中制造同供应商同发票号,执行必须返回 `duplicate_invoice``action=inspect_existing_record``retryable=false/planInvalidated=true`;桌宠显示固定下一步、错误码和关联 ID,同一计划再次请求必须在确认框和数据库调用前被拒绝。
- 分别在确认后改变采购开放来源、请假日历/冲突/假别或流转类别配置,必须返回稳定变化码与 `action=replan`,旧计划立即撤销;客户请假过程即使返回包含内部 SQL/对象名的自由 `reason`,计划警告和执行错误也只能使用固定公开文案,不得把原始 SQL Server 消息、对象名、物理字段或业务值带到 Host、桌宠、AstrBot 或 MiniMax。
- 在 ERP 原生确认框点击取消,必须返回 `user_cancelled``action=review_and_retry`,证明没有写入且原预览仍可再次核对;模拟桥超时或固定 `workflow_database_error` 时必须返回 `action=reconcile_execution` 并复用原宿主幂等键,先核对 ERP 窗口、业务记录和审计,不能盲目生成第二张单据。
- 向测试 Host 注入额外 `sql/physicalField`、未知 `action=run_sql`、字符串布尔值或控制字符,命名管道验证、Host 白名单投影或页面协议校验必须失败关闭;普通用户最终只能看到固定恢复说明和关联 ID。
## 3. 客户存储过程实现
`SqlServer/002_workflow_adapter_contract.sql` 为接口契约,对当前客户实现白名单动作,并部署只读的 `SqlServer/006_workflow_readiness_v3.sql` 作为运行时门禁。不得改为动态 SQL、任意存储过程名或模型可控表名。实施前必须读取当前业务数据库的 `sys.databases.compatibility_level`:级别 `130` 及以上实现 JSON 参数过程 `p_lserp_agent_workflow_read`;低于 `130` 时使用 `p_lserp_agent_workflow_read_compat100`,JSON 只在受信任 ERP 进程中按固定动作解析,并仅传入契约声明的标量参数。兼容采购写只允许精确过程 `p_lserp_agent_workflow_write_purchase_compat100` 接收固定标量和受信任 ERP `XmlWriter` 生成的限量行集;兼容请假写只允许精确过程 `p_lserp_agent_workflow_write_leave_compat100` 接收固定强类型标量。两条路径均须完成独立 DBA 评审、NOEXEC 编译、目标菜单编辑权限与业务行范围复核、回滚/持久幂等/审计集成验收和 TrustedPeople 签名;任一条件缺失时不得注册,也不得退化为动态 SQL 或任意过程调用。V3 门禁必须逐项核对实际选用过程的有序参数签名和修改时间;签名漂移或验收后改过程时必须失败关闭并重新验收。
每个写动作必须在同一个 `SERIALIZABLE` 事务中同时完成:
1. 根据当前账套、子系统和用户再次校验权限。
2. 重新读取来源单/日历/冲突/审批状态,比对预览指纹。
3. 写入业务主表、明细、关联和工作流记录。
4. 写入 `p_agent_command_idempotency``p_agent_business_audit` 和必要的 `p_agent_integration_outbox` 记录。
5. 返回契约规定的 `success/code/message/record_id`、实际幂等键与输入指纹、事务证据 ID 和业务审计 ID;任何证据缺失都回滚。
只读过程完成后,复制并填写 `Lskj.Cli/adapter-examples` 中的两份契约探针。只允许使用验收库中的脱敏测试数据,采购探针发票号必须尚不存在,请假探针记录必须是当前用户可提交的测试草稿:
```text
lserp-cli adapters verify-contract purchase --input <purchase-probe.json> --output <new-purchase-read-evidence.json> --user <管理员>
lserp-cli adapters verify-contract leave --input <leave-probe.json> --output <new-leave-read-evidence.json> --user <管理员>
lserp-cli adapters verify-contract-evidence --input <new-purchase-read-evidence.json>
lserp-cli adapters verify-contract-evidence --input <new-leave-read-evidence.json>
```
在线探针只调用固定白名单 read 动作;失败时仍新建证据文件并返回退出码 6。证据绑定账套、子系统、管理员、模块、探针输入 SHA-256 和检查结果,但不保存发票号、员工号、物料、原因或记录号。哈希完整性不能证明客户过程内部没有动态 SQL,参数化查询仍须人工代码审查;证据中的 `registrationReady` 固定为 `false`
## 4. 采购附件闭环
至少使用一张真实脱敏发票图片、一份 PDF 和一份 XLSX/CSV 明细测试;每次只允许 1–3 份附件,单份源文件不得超过 12 MB,宿主总量不得超过“数量 × 单文件上限”(默认 36 MB),Schema、共享内核、兼容网关、验收投影和客户存储过程必须使用同一单文件上限:
- 固定调用链为 `purchase.invoice.resolve -> purchase.invoice.create`。第一步只把供应商名称/税号、币种、物料名称/规格/单位解析成 ERP 编码,不能落库;OCR 中看似存在的编码也必须经过 ERP 只读过程复核。解析结果包含绑定当前用户、账套、子系统和完整创建输入的 5 分钟 HMAC `resolutionProof`,第二步必须原样携带;改动任一编码、跨会话复用或过期时,必须在查询业务表前拒绝。第二步才查询开放来源、做确定性匹配并生成写入预览。
- `purchase.resolve_supplier/resolve_currency/resolve_material` 必须只按精确编码、税号、全称或人工维护别名匹配当前账套有效主数据;零结果或多结果时返回候选并停止,严禁 `TOP 1`、相似度最高自动选择或模型自行补编码。
- 启用采购适配器时 `lineAmountMode` 必须明确为不含税或含税,不能使用 `None/0`。输入必须包含发票头不含税金额、税额、价税合计和每行税额;CommandKernel 按 `currencyScale`、四舍五入与行/头容差复核“数量×单价、行金额×税率、明细汇总、头部价税恒等式”,任一不平都不得产生可执行计划。共享内核还强制数量容差不超过 `0.01`、单价绝对/相对容差不超过 `1/1%`、税率容差不超过 `0.001`、行/头金额容差不超过 `1/5`;运行配置和验收探针都不能绕过。客户写过程在事务内还必须独立重算一次。
- 发票日期只接受严格 `YYYY-MM-DD`(例如 `2026-08-11`),不接受任何时间或时区。分别用 `T00:00:00``Z``+08:00`、不存在日期和区域格式日期验证 Schema 在主数据查询前返回 `input_schema_violation`;直接调用处理器的 UTC/Local/非零时间 `DateTime` 也必须返回 `purchase_invoice_date_invalid`。最终发布策略必须把 `purchase.invoice.resolve/create` 都锁定为 `commandVersion=1.4`;保留 `1.2/1.3` 必须因合同漂移被拒绝。
- 开放来源必须返回稳定采购单标识、人工单号、采购明细标识、供应商、币种、物料、单位、剩余数量、原币单价、税率和正汇率。单位不同不得匹配;一张发票命中不同汇率必须拆单或由财务重新确认。剩余数量要扣除全部未删除、未取消、未作废的既有单据占用,查询超过 10000 行时失败关闭,不能截断后继续匹配。
- 准备同一供应商、币种下分别属于两个“组织 + 部门 + 采购员”元组的有效采购来源 A/B,只给当前测试用户签署 A 的 `p_agent_purchase_row_scope`。通过桌宠/AstrBot 执行 `purchase.invoice.resolve` 并进入来源匹配时,桥响应、模型上下文和日志只能出现 A,B 的单号与明细标识均不得出现;删除、过期或破坏 A 的审批哈希后必须返回 `purchase_row_scope_denied` 且不查询出任何来源。再以精确内置管理员账号复测,结果仍不得绕过行级范围。
-`acc_1007` 中分别准备主表 `visible=0/1`、明细 `isVisible=0/1` 和字段权限导致有效宽度为 0 的测试字段;`adapters inspect/validate-fields` 必须只把主表 `visible=1`、明细 `isVisible=0` 且有效宽度大于 0 的字段视为可映射。任何隐藏物理列必须返回 `mapped_field_not_exposed` 或不进入候选,不能因管理员登录而绕过。
- 上传目录先完成杀毒/隔离;AstrBot 以专用低权限 Windows 服务账号运行。电子 PDF 必须使用随包 PDFium 最多三页隔离渲染、逐页 MiniMax 严格识别和跨页合并,生成的 `pdfium_minimax_pages_v1` 必须与源文件摘要、每页 PNG 摘要及精确提取摘要一起进入 `resolutionProof`、输入指纹、XML v3 写载荷和 `p_agent_business_source_document.preprocess_contract`。图片、CSV、XLSX 分别只能使用 `minimax_vlm_0.0.4``document_sandbox_csv_v1``document_sandbox_xlsx_v1`;后缀与合同不匹配必须在业务查询前拒绝。验证文档解析 worker 继承不到 MiniMax Key 和代理凭据,不能联网、写文件或再启动子进程,CPU、内存、超时、输出和进程数限制均生效。
- 使用超大、加密、截断、畸形、宏、外链和公式样本测试;worker 必须 fail-closed,超时或超限后整个进程树被回收,错误只返回稳定分类,不返回路径、堆栈或文档内容。另以受控测试工具在来源摘要生成后替换图片或文档(含替换后再恢复),视觉网络请求或文档解析必须以 `attachment_changed_during_preprocess` 停止,不能生成 ERP 计划;正常样本返回的来源摘要必须等于实际发送/解析字节。
- 唯一匹配:供应商、币种、物料、单位、数量、原币含/不含税单价、税率、汇率、行金额和来源行全部命中,生成可确认预览。
- 确认前必须直接核对桌宠中的可信服务端预览,而不是只看模型回复:16 个发票汇总字段必须完整显示,随后逐行列出发票行号、物料、本次数量/单位/单价/税率/税额/行金额,以及匹配到的采购单号、来源明细、来源剩余数量/单位/单价/税率/汇率。使用 1 行、3 行和 200 行边界样本确认预览区可滚动且最终确认按钮始终可达;删除任一逐行字段、把 `candidateCount` 改为 2、加入问题项、让兼容别名与来源事实不一致或让本次数量超过来源剩余数量时,宿主和桌宠都必须以 `plan_invalid`/“逐行匹配证据不完整”失败关闭,不得出现可执行按钮或 ERP 原生确认框。
- 歧义匹配:至少两个来源行同样匹配时,Agent 只显示候选和差异,不生成可执行计划。
- 澄清续接:上传附件后分别制造供应商、币种、物料或来源行多候选,第一轮必须保留附件;用户在下一轮补充唯一选择时不得要求重新上传。最终 `purchase.invoice.create` 计划中的 `sourceDocumentCount` 必须等于待处理附件数,`sourceDocumentSetSha256` 必须按本文件第 8 节/`WRITE_ACCEPTANCE.md` 的固定算法与本地原文件集合一致。删除字段、修改数量或摘要时,宿主必须返回 `attachment_plan_binding_invalid`、移除可信计划、保留附件且不出现确认按钮;请假、诊断或普通回复也不得顺带清空采购附件。
- 超额与变化:一张发票多行聚合超出剩余数量,或预览后来源行的内部标识、人工单号、单位、剩余数量、单价、税率、汇率被他人修改,必须返回 `purchase_source_changed` 并要求重新预览;人工单号变化即使内部主键未变也不得沿用旧确认。
- 幂等重放:同一 `idempotencyKey + 输入指纹` 返回原结果,不新增第二张单;同 Key 不同输入直接拒绝。
- 确认边界:模型文本中的“已确认”无效,必须先点桌宠按钮,再点 ERP 原生确认窗口。
- 关联链:resolve 与固定 create 续接、最终预览、桌宠执行和 ERP 计划/完成审计必须使用同一个 `bridgeCorrelationId`;修改页面执行请求的关联 ID 必须在进入命名管道前返回 `plan_correlation_mismatch`。再用协议测试工具保留同一 `clientSessionId``planId`、只调换关联 ID,ERP 进程内桥也必须在弹出原生确认窗口及占用幂等键前返回同一码;两种负例的业务表和审计表均不得新增记录。
## 5. 请假闭环
- 固定测试链为 `hr.leave.resolve -> hr.leave.create -> hr.leave.submit(可选)`。解析命令只返回 `resolvedCommand/resolvedInput`,不能落库;`resolvedInput` 必须包含绑定当前用户、账套、子系统、员工、假别、流程、本地时段、日历工时、原因和提交意图的 5 分钟 HMAC `resolutionProof`。创建命令必须原样复核;绕过解析直接拼输入、修改任一字段、跨会话复用或过期时,应在读取请假业务数据前返回 `leave_resolution_invalid`/`leave_resolution_proof_expired`。创建与提交各自重新预览和确认。
- 最终 `hr.leave.create` 确认预览必须完整且只包含员工、请假类型、流转类别、无时区开始/结束时间、核算工时、原因和固定为 `false` 的“创建后提交”八项;`hr.leave.submit` 的第二次预览必须完整且只包含申请编号与固定动作“提交审批”。桌宠顶层预览必须与服务端 `data.preview` 逐值一致。分别删除原因、替换起止时间为带 `Z/+08:00` 的值、把“创建后提交”改为 `true`、增加未知字段或把提交动作改为其他文字,宿主和桌宠都必须返回 `plan_invalid`/“请假确认信息不完整”,不得出现可执行按钮或 ERP 原生确认框。
- 用“我明天下午请事假,原因是去医院”验证:`employeeId` 来自当前 ERP 会话,`leaveTypeCode` 来自 `leave.resolve_type` 的唯一结果,开始/结束来自 `leave.resolve_calendar_range`,预览必须显示客户时区和员工日历工时。再用测试日之后的“本周五下午”或“下周一上午”以及未写年份的“M月D号下午”验证 `hr.leave.resolve` `1.4`:星期按周一为一周开始,月日取 ERP 本地时间下尚未过去的最近一次,跨年时进入下一年;AstrBot 必须原样传递表达,不能使用模型时钟换算。`flowTypeCode` 必须来自 `leave.resolve_flow_type` 的当前有效配置行 id;不唯一时桌宠必须展示候选并追问。
- 用一个已知员工排班总工时的绝对日期表达(例如“我从 2026-08-12 下午到 2026-08-14 上午请事假,共 11 小时”)验证多日区间:两端分别调用员工日历边界,测试输入必须把已知总工时作为一致性断言;完整区间总工时必须由 `leave.calculate_hours` 重新核算并与断言一致,再用于流程类别解析、短期凭证、创建输入和二次预览。任一端没有明确上午/下午/全天、区间反向、跨度超过 `maximumCalendarDays`、两端时区不一致、工时不符或日历总工时为零时必须阻断;周末或非工作日不能由模型自行扣减工时。
- `hr_4011` 当前天数/岗位联动仍引用已失效的流程 id 3195-3200,而有效审批步骤使用 3629-3634。修复并签署该配置前,禁止按岗位名称或“五天内/以上”文案自动选路;验收还要确认创建记录已派生请假人姓名、部门、岗位和天数,否则后续审批人解析可能错误。
- `leave.resolve_type` 必须只查询当前员工可用的已启用假别和人工维护别名;零结果或多结果时返回稳定问题代码和候选项,不生成写入计划。
- “明天”但未说明上午/下午/全天、裸“周一/星期一”、已经过去的“本周X”、不存在的“2月30日”、超出未来 366 天、客户日历无可申请时段,都必须停止;不得由模型补范围、日期或时间。
- `allowPastStart=false` 时,用已过当天时段(例如下午再申请“今天上午”)验证解析阶段返回 `leave_start_in_past`,且不产生 `resolvedInput`。明确传入与员工日历不一致的 `requestedHours` 时应返回 `leave_requested_hours_mismatch`;未明确说出工时时 AstrBot 必须省略该值。请假开始/结束和日历解析结果只接受 `DateTimeKind.Unspecified` 的无时区本地时间;直接注入机器 `Local` 或 UTC 时间必须在生成解析凭证和业务查询前拒绝。
- 当前用户无代申请权限时,`employeeId` 只能是当前员工。
- 停用假别、非工作时间、超最大天数、工时不符、时间冲突和预览后规则变化都必须阻断。自然语言没有手填工时时,`requestedHours` 必须取 ERP 日历核算值并进入解析凭证与输入指纹;原生确认后即使排班只变化 `0.01` 小时、仍位于普通工时容差内,也必须返回 `leave_request_changed` 重新预览,不能按新工时静默创建。
- `hr.leave.create` 只创建草稿;`submitAfterSave=true` 只能在创建成功响应中产生新的 `hr.leave.submit` 预览,不得自动执行。验收时在第一次确认后核对提交计数仍为零,再用新的幂等键完成第二次桌宠确认和 ERP 原生确认;两次操作必须有不同的计划号、输入指纹、事务证据和审计记录。
- 验证 `draft/read` 计划的 `executionAllowed=false`,桌宠按钮不可用,且 ERP 桥中不存在可执行的服务端计划。
- 创建及其服务器后续提交计划必须保留同一个 `bridgeCorrelationId`,但计划号、输入指纹、幂等键、事务证据和业务审计号仍各自独立;验收截图、桥审计和数据库审计用该关联 ID 贯通。
## 6. 配置与 SQL 诊断闭环
- 用可恢复的测试配置制造“缺字段、缺权限、无效关联、初始化 SQL 失败”四类问题。
- `module.trace-initialization` 的关键确认预览必须完整且只包含模块编号、导航编号、模块名称、`alreadyOpen=false``traceSupported=true`、固定采集范围 `current_erp_managed_ui_thread``forceTerminationSupported=false``maxEvents=200``maxDurationSeconds=20` 九项;服务端数据还必须包含相同限制、固定采集策略和静态诊断快照,警告必须明确“20 秒仅限制 SQL 证据采集窗口”且旧模块无法安全强制终止。分别删除模块名称、把强制终止改为 `true`、把事件上限改为 201、删除风险警告或让顶层预览与 `data.preview` 不一致,宿主和桌宠都必须返回 `plan_invalid`/“诊断范围或风险说明不完整”,不得出现 ERP 原生确认框或启动模块。
- 诊断只返回模块编号、配置缺失、稳定错误分类、关联 ID、修复建议,以及由 SQL 关键字/运算符和会话内 `id_####``@p_####``caller_####` 组成的安全结构。客户表名、字段名、存储过程名、参数名、调用类名、字面量、参数值、密码、连接串和完整内部 SQL 都不得传给 AstrBot、MiniMax 或写入诊断证据;离线验证器必须拒绝即使已经重算内容哈希的原始标识符。
- 用受控测试桥在成功结果的自由 `message/data` 中放入原始 SQL、物理对象名和“忽略规则”提示词。Host 给页面的回执必须只剩固定成功消息与精确诊断投影;额外诊断属性、未知结果码、计数或哈希不一致必须返回 `bridge_protocol_error`,且不得保存任何待用对话证据。
- 追踪成功后立即追问“具体哪里配置错了”,用隔离 AstrBot 测试接收器确认只出现一次 `[LSERP_TRUSTED_EXECUTION_EVIDENCE_V1_BEGIN]...END` 独立消息部件,块内不含上一步的 SQL、物理对象名或提示词文字。完整流成功后再次提问不得重复出现;把时钟推进超过十分钟也不得出现;让第一轮流中断时证据应保留供同一会话重试。切换数据库、用户、账套或子系统后必须清除,用户在正文中手写保留标记必须以 `chat_text_invalid` 拒绝且零 AstrBot 调用。
- 用一个普通客户端异常模拟包含“Invalid column/权限/SQL”等数据库相似文字但没有失败 SQL 事件且异常链中没有 `DbException` 的场景,`module.trace-initialization` `1.2` 必须返回 `module_initialization_error``confidence=inferred`,不得误报缺字段或数据库权限;再用真实 `DbException` 或失败 SQL 事件验证稳定数据库分类仍然成立。
- 再准备一个进程内测试模块:直接使用 ADO.NET 触发数据库异常,在模块内部捕获后只调用旧 `LogHelper.WriteError`,同时让窗体仍可打开。追踪必须通过同一 UI 线程的短时日志观察取得真实 `DbException` 分类并把结果标为数据库错误,但响应、证据、审计和模型上下文不得出现原始异常消息、连接串、表名、字段名或 SQL。把相同日志移到后台线程时不得被当前 UI 追踪误收;把异常换成仅在文本中写“Invalid column”的普通异常时只能返回推断性客户端结论。确认页的 `capturePolicy` 必须明确:SQL 明细只覆盖 `Lskj.Core.SqlHelper`,直接 ADO.NET 最多取得同线程已记录的异常分类,不能宣称覆盖其 SQL 文本。
- 分别准备独立 EXE、网页/外部资源、旧版原生 LSP 和动态启动目标的隔离菜单配置;追踪计划必须返回 `valid=false``executionAllowed=false``outcomeCode=module_trace_scope_unsupported`,不弹确认、不启动目标且不生成伪 SQL 证据。再把一个已计划的进程内模块在确认前改为外部边界,执行必须以 `module_configuration_changed` 失败且零启动;恢复后重新计划。`DllName`、URL 和参数不得出现在桥响应或审计中。
- 非管理员只能获得用户级错误说明;管理员证据查询也必须记录审计。
- 计划响应不得出现 `MenuId/DllName/PurviewId/UrlParams`、原始异常消息或 CLR 异常类型;确认后修改菜单配置或任一低代码静态诊断配置(包括把初始化 SQL 改成相同长度的其他内容),执行必须通过服务端私有完整配置指纹在打开模块、采集 SQL 和写证据前返回 `module_configuration_changed` 并要求重新预览。私有指纹和参与哈希的 SQL/表/字段不得投影到计划、审计或模型上下文;仅数据库字段行返回顺序变化不得误报。提前打开模块必须返回 `module_already_open`
- 重复故障必须按错误码、SQL 指纹和调用点归并并保留出现次数;超过 20 秒证据窗口/200 条时返回 `trace_truncated`AstrBot 必须把 `confidence=inferred` 和截断结果表述为待复核,不得生成修复 SQL。必须向验收人员明确:20 秒不是模块打开硬超时,无法安全强制终止卡住的旧 WinForms 初始化;疑似卡死场景只允许在可回滚的隔离测试环境复现。
- 验收包保留 `diagnosticId`、桥 `correlationId``primaryFindingCode`、静态诊断和脱敏事件;使用相同管理员、账套、子系统及测试数据复现。
- 检查 `Log/AgentBridge/diagnostics/<diagnosticId>.json` 为不可覆盖单文件、内容不超过 2 MB、SHA-256 与 `content` 一致且身份作用域正确;模拟目录只读/磁盘失败时返回 `evidencePersisted=false``*_evidence_unavailable`,不得自动重新打开模块。生产目录应限制为 ERP Windows 用户/运维审计账号,并配置留存、归档和安全删除周期。
- 在未配置数据库的隔离机运行 `lserp-cli diagnostics verify-evidence --input <file>`,必须成功且不触发 ERP 登录;分别注入重复属性、JSON 注释、未知字段、错误计数、身份范围篡改和哈希篡改,必须返回稳定非零错误。输出的 `signatureVerified=false` 需由外部签章流程补齐。
## 7. 交付证据
每个客户/账套保留一套不含业务隐私和秘密的验收包:
- 已人工签字的字段映射与存储过程版本哈希。
- 采购、请假只读契约探针证据及离线哈希校验结果。
- 每个启用工作流的 RSA-SHA256 签名验收清单、TrustedPeople 公钥证书 thumbprint、有效期,以及与 V2 验收证据行相同的 `evidence_sha256`、账套和子系统;清单还必须绑定最终部署的 `business-adapters.json`、客户 1.2 只读画像、字段映射、只读契约与写集成报告的原始字节 SHA-256。签发前最终 CLI 必须在线复核画像、本工作流批准状态与零未关闭阻断项,签发脚本还会校验每个阻断解决哈希与清单的精确制品哈希一致,并要求画像选定模块与清单 `moduleCode` 逐字一致。运行时也会在启动、计划和确认执行前重新检查批准状态、模块、解决哈希,并以 V3 就绪查询核对当前过程签名、修改时间及只读系统目录;配置、画像阻断状态、模块、证据文件、关键列或过程参数变化后必须重新签收,旧表布尔值不得作为启用依据。
- 权限、匹配、冲突、事务回滚、幂等和审计的自动化测试报告。
- 先在客户已验证备份/恢复且明确非生产的可恢复 UAT 库,由提升权限的 Windows PowerShell 5.1 使用 `New-WorkflowUatAuthorization.ps1` 签发最长 24 小时授权。授权必须精确绑定客户、环境、ERP 用户、运行配置、画像、发布策略、最终 ZIP 以及签名 ERP/CLI,并为采购 13 项、请假 19 项固定用例分别生成不可复用令牌。令牌库由 DPAPI CurrentUser、受限 NTFS ACL 和高完整性标签保护,只供现场采集器读取,不能进入 ZIP、聊天、日志或总验收目录;生产库禁止签发或加载该授权。
- 使用 `New-WorkflowWriteUatCampaign.ps1` 建立受限、不可覆盖的固定活动目录;生成器与 `Test-WorkflowWriteUatCampaign.ps1` 必须共同验证随包 `workflow-write-uat-case-catalog.v1.json` 的内置 SHA-256,活动清单也绑定同一哈希及管理员验签 CLI、受限运行 CLI 两种身份。每次开始或恢复前,检查器用管理员 CLI 离线验签,只用 `lserp-agent-cli.exe` 运行 `version` 和桥 `health`,并验证 ERP PID、令牌库 ACL 与覆盖、已有单用例和完整用例关系。活动工具没有 execute 路由、不解密令牌且绝不批量写库;32 项仍逐项由验收人员按目录准备场景、确认、DBA 只读复核和采集。版本化目录不含客户数据或可执行 SQL,活动目录含受限测试输入;两者都不属于最终 23 个制品,验收结束后按客户数据销毁流程处理活动目录。
- 单用例原始响应由 `Invoke-WorkflowWriteCaseCapture.ps1` 采集:管理员 `lserp-cli.exe` 只验证授权并投影证据,受限 `lserp-agent-cli.exe` 才能执行 `version``bridge health/context/plan/execute`。脚本分别锁定并验证两者的 SHA-256/签发者,绑定运行 CLI 的精确版本和 ERP PID,以同一关联 ID 自动完成采购或请假的 `resolve -> create`,授权令牌和幂等键都只走标准输入。服务器 `resolutionProof` 只在受限临时目录中用于后续计划,最终仅保留 `schemaVersion=1.3` 脱敏索引投影;DBA 观察值仍由验收人员提供。采购提交/重放/审计证据会再次独立校验完整创建 Schema、明确成功结果以及计划附件数量/集合摘要,缺少发票日期、金额或明细时不能靠成功标签通过。
-`New-WorkflowWriteIntegrationEvidence.ps1` 生成且经最终 `lserp-cli adapters verify-write-integration-evidence` 验证的 `schemaVersion=1.6` 采购、请假写集成报告;报告必须绑定相同客户 `schemaVersion=1.2` UAT 授权的原始文件/内容/授权 ID 哈希、每个固定用例唯一令牌哈希和运行 CLI 版本/SHA-256/签发者,以及相同源码提交、商用 ZIP、运行时配置、模块、账套和子系统。每个用例还要证明同一 ERP PID 上下文关联 ID、用户编号哈希、用户名哈希、数据库作用域、管理员状态以及实际命令名、版本、风险和固定计划有效期,覆盖采购 13 项、请假 19 项固定场景,且结果码、解析问题码、确认阶段、来源文件贯通、跨用例记录关系、事务、幂等和审计证据全部匹配。
- 三条端到端闭环的关联 ID、计划指纹、业务记录 ID 和审计 ID。
- 代码签名、安装包哈希、依赖版本、数据保留/销毁策略和回滚手册;商用预检必须是 `schemaVersion=1.7`,其 `packageSha256` 必须等于最终 ZIP,声明 `miniMaxIntegrationMode=direct_https_vlm`,并绑定 guga 授权、AstrBot AGPL/EULA 合规审查、MiniMax API 服务审查,以及预检前 24 小时内合成图片在线探针原始 JSON 的 SHA-256、观测时间、区域和合同版本。预检检查项必须无重复、全部为 `passed=true/code=ok`,且包含当前版本的 `package_archive_binding``guga_supply_chain_audit``sqlserver_compatibility100_syntax``workflow_uat_case_catalog``minimax_online_vision_probe_evidence``pdf_invoice_pipeline``attachment_snapshot_binding``erp_session_scope``guga_supply_chain_audit` 必须证明包内只有锁定的上游审计而没有在线下载的 guga 素材,独立的 `guga_commercial_license_evidence` 仍须绑定实际包外精灵图摘要。即使手工保留顶层 `passed=true`,缺少门禁、目录/探针过期或篡改、或来自同一源码提交下另一个 ZIP 的旧报告也不能进入客户总验收包。
最后把以下 23 个文件以互不重复的纯文件名放进同一个只读目录:最终商用 ZIP、`business-adapters.json`、客户只读画像、最终命令发布策略、商用预检、MiniMax 在线探针、`LEGACY-BUILD-EVIDENCE.json`;采购的单工作流 UAT 授权、签名清单、写集成报告、1.5 只读预检和 1.1 现场交接;请假的同五份文件;诊断管理员会话的 1.5 只读预检、1.1 现场交接和四份诊断原始证据。审批输入原文和令牌库不属于制品。执行 `New-CustomerAcceptanceBundle.ps1` 时除管理员 `-VerifierCliPath` 外,还必须提供从最终 ZIP 解包且已签名的 `-RuntimeCliPath``-ExpectedRuntimeCliVersion`,以及两份 UAT 文件、三组会话文件和三个子系统。生成器会从最终 ZIP 内的 `SHA256SUMS.json` 读取 `Host/lserp-agent-cli.exe` 条目,核对外部运行时文件的版本、大小、SHA-256、Authenticode 签发者和实际 `version` 响应,并要求三份预检及交接绑定同一运行时身份。随后写入 `schemaVersion=1.8` 临时总包,并由管理员验证 CLI 离线复核 23 个文件后才原子发布。采购交接只能声明采购角色,请假交接只能声明请假角色,诊断交接只能声明诊断角色且预检必须为管理员;支持模块可同会话存在,但不能冒充业务角色。任何运行时/验证器角色混用、跨会话交换、合并授权、串子系统/PID/用户、串提交、串 ZIP、串数据库作用域、证据篡改或签名失败都不会发布输出文件。
在隔离验收机安装相同 TrustedPeople 公钥证书后复验:
```text
lserp-cli acceptance verify-customer-bundle --input customer-acceptance.json --evidence-root <验收目录> --source-commit <40位提交> --package-sha256 <最终ZIP哈希> --account-book <账套> --purchase-subsystem <采购子系统> --leave-subsystem <请假子系统> --diagnosis-subsystem <诊断子系统> --database-scope-fingerprint <已核准的64位数据库作用域指纹>
```
成功输出仍固定 `registrationReady=false`。总包是发布与客户签收证据,不替代 ERP 启动、计划和确认时对当前 V3 就绪结果及其 V2 验收证据行、低代码配置、权限和运行时过程的再次检查。